注解和反射02:反射

一、什么是反射

1、概述

  • JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制

2、获取反射class对象的三种方式

  • 获取反射对象代码演示
public class 反射对象的创建方式 {
    public static void main(String[] args) throws ClassNotFoundException {

        Person person = new Student();

        //方式一:通过类名获得class对象
        Class<Student> c1 = Student.class;
        //方式二:通过对象获得class对象
        Class<? extends Person> c2 = person.getClass();
        //方式三:通过类的全路径获得class对象
        Class<?> c3 = Class.forName("com.lc.反射.Student");

       //获得父类的类型
        Class<? super Student> c5 = c1.getSuperclass();
        System.out.println(c5);

    }
}
  • 运行结果
    在这里插入图片描述

二、反射操作类的所有信息

  • 代码演示
public class 获得类的信息 {
    public static void main(String[] args) throws Exception {
        //获得类的class对象
        Class<?> c1 = Class.forName("com.lc.entity.User");

        //获得类的名称(包名+类名)
        System.out.println("获得类的名称(包名+类名)------>"+c1.getName());
        System.out.println("======================");

        //获得类的简单名称(类名)
        System.out.println("获得类的简单名称(类名)------>"+c1.getSimpleName());
        System.out.println("======================");

        //只能获得public属性
        Field[] fields = c1.getFields();
        for (Field field : fields) {
            System.out.println("public属性------>"+field);
        }
        System.out.println("======================");

        //获得所有的属性
        Field[] declaredFields = c1.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("获得所有的属性------>"+declaredField);
        }
        System.out.println("======================");

        //获取指定的属性
        Field name = c1.getDeclaredField("name");
        System.out.println("获取指定的属性------>"+name);
        System.out.println("======================");

        //获取本类及其父类的所有的public方法
        Method[] methods = c1.getMethods();
        for (Method method : methods) {
            System.out.println("获取本类及其父类的所有的public方法------->"+method);
        }
        System.out.println("======================");

        //获得本类的所有的方法
        Method[] declaredMethods = c1.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("获得本类的所有的方法-------->"+declaredMethod);
        }
        System.out.println("======================");

        //获取指定的方法
        Method getName = c1.getMethod("getName", null);
        System.out.println("获取指定的方法------->"+getName);
        System.out.println("======================");

        //获得public的构造器
        Constructor<?>[] constructors = c1.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("获得public的构造器----->"+constructor);
        }
        System.out.println("======================");

        //获得所有的构造器
        Constructor<?>[] declaredConstructors = c1.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("获得所有的构造器------->"+declaredConstructor);
        }
        System.out.println("======================");

        //获取指定的构造器
        Constructor<?> constructor = c1.getConstructor(String.class, int.class, int.class);
        System.out.println("获取指定的构造器------->"+constructor);
    }
}

  • 运行结果
    在这里插入图片描述
    在这里插入图片描述

三、反射获取泛型

  • 代码演示
//通过反射获取泛型
public class 反射获取泛型 {

    public void test01(Map<String, User> map, List<User> list){
        System.out.println("test01");

    }

    public Map<String,User> test02(){
        System.out.println("test02");
        return null;
    }
    public static void main(String[] args) throws Exception {
        Class c1 = 反射获取泛型.class;

        Method method1 = c1.getMethod("test01", Map.class, List.class);
        Type[] genericParameterTypes = method1.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println("test01泛型外部类型---->"+genericParameterType);
            if (genericParameterType instanceof ParameterizedType){
                Type[] actualTypeArguments =  ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println("test01泛型内部类型---->"+actualTypeArgument);
                }
            }
        }

        Method method2 = c1.getMethod("test02", null);
        Type genericParameterTypes1 = method2.getGenericReturnType();
            if (genericParameterTypes1 instanceof ParameterizedType){
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterTypes1).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println("test02返回值泛型类型---->"+actualTypeArgument);
          }
       }
    }
}
  • 运行结果
    在这里插入图片描述

四、反射动态的操作对象

  • 代码演示
//,通过反射动态的创建对对象
public class 动态的操作对象 {
    public static void main(String[] args) throws Exception {
        //获得class对象
        Class<?> c1 = Class.forName("com.lc.entity.User");
        //构造一个对象,本质是调用了类 一个无参构造器
        System.out.println("==============================================");

        //通过构造器创建对象
        Constructor<?> declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        User u = (User) declaredConstructor.newInstance("廖常", 11, 24);
        System.out.println("通过构造器创建对象------>"+"姓名:"+u.getName()+"年龄:"+u.getAge()+"   ID:"+u.getId());
        System.out.println("==============================================");

        //通过反射获取方法
        User user = (User) c1.newInstance();
        Method setName = c1.getMethod("setName", String.class);
        setName.invoke(user,"廖常哈哈");
        System.out.println("通过反射获取方法------->"+user.getName());
        System.out.println("==============================================");

        //通过反射操作属性
        User user1 = (User) c1.newInstance();
        Field name = c1.getDeclaredField("name");
        //不能直接操作私有属性,需要关闭程序的安全检测,或者name.setAccessible(true)
        name.setAccessible(true);
        name.set(user1,"小常常");
        System.out.println("反射操作私有属性------->"+user1.getName());   
    }
}
  • 运行结果
    在这里插入图片描述

五、new对象和反射操作 对象性能测试

  • 代码演示
//分析性能问题
public class 性能测试 {
    public static void main(String[] args) throws Exception {
        test01();
        test02();
        test03();

    }
    //普通方式
    public static void test01(){
        User user = new User();
        long start = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            user.getName();
        }
        long end = System.currentTimeMillis();

        System.out.println("普通方式执行10亿次需要----->"+(end-start)+"毫秒");

    }

    //反射不关闭检测方式
    public static void test02() throws Exception {
        User user = new User();
        long start = System.currentTimeMillis();
        Class<? extends User> c1 = user.getClass();
        Method getName = c1.getDeclaredMethod("getName", null);

        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user,null);
        }
        long end = System.currentTimeMillis();
        System.out.println("反射不关闭检测方式执行10亿次需要----->"+(end-start)+"毫秒");

    }

    //反射关闭检测方式
    public static void test03() throws Exception {
        User user = new User();
        long start = System.currentTimeMillis();
        Class<? extends User> c1 = user.getClass();
        Method getName = c1.getDeclaredMethod("getName", null);
        getName.setAccessible(true);

        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user,null);
        }
        long end = System.currentTimeMillis();
        System.out.println("反射关闭检测方式执行10亿次需要----->"+(end-start)+"毫秒");

   }
   
}

  • 运行结果
    在这里插入图片描述

六、反射操作注解

  • 创建一个Stu类
@Table("db_stu")
public class Stu{
    @Field(columnName = "db_id",type = "int",length = 10)
    private int id;
    @Field(columnName = "db_name",type = "varchar",length = 10)
    private String name;
    @Field(columnName = "db_age",type = "varchar",length = 3)
    private int age;

    public Stu() {
    }

    public Stu(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Stu{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

  • 创建一个Table注解
//类名注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table{
    String value();
}
  • 创建一个Field注解
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Field{
    String columnName();
    String type();
    int length();
}
  • 测试
//通过 反射操作注解
public class 反射操作注解 {
    public static void main(String[] args) throws Exception {
        Class<?> c1 = Class.forName("com.lc.entity.Stu");
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("获取注解---->"+annotation);
        }

        //获取注解value的值
        Table table = c1.getAnnotation(Table.class);
        System.out.println("获取注解value的值----->"+table.value());

        //获得指定属性上的注解的值
        java.lang.reflect.Field name = c1.getDeclaredField("id");
        Field annotation = name.getAnnotation(Field.class);
        System.out.println("获得指定属性上的注解的值---->"+annotation.columnName());
        System.out.println("获得指定属性上的注解的值---->"+annotation.length());
        System.out.println("获得指定属性上的注解的值---->"+annotation.type());
    }
}

  • 运行结果
    在这里插入图片描述

七、类加载器

1、什么是类加载器

  • Java类加载器是Java运行时环境的一部分,负责动态加载Java类到Java虚拟机的内存空间中。类通常是按需加载,即第一次使用该类时才加载。由于有了类加载器,Java运行时系统不需要知道文件与文件系统

2、类加载器是干什么的

  • 类加载器它是在虚拟机中完成的,负责动态加载Java类到Java虚拟机的内存空间中,在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例

3、类加载器的类型

1.启动类加载器,没有父类
2.拓展类加载器由Java语言实现,父类加载器为null
3.系统类加载器,由Java语言实现
4.自定义类加载器,父类加载器肯定为AppClassLoader

4、获取类加载器

  • 代码演示
public class 获取类加载器 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取系统类的加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println("系统类的加载器------>"+systemClassLoader);

        //获取系统类加载器的父类加载器--->扩展类加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println("父类加载器--->"+parent);

        //获取扩展类的父类加载器----->根加载器(c/c++)
        ClassLoader grandParent = parent.getParent();
        System.out.println("根加载器---->"+grandParent);

        //获取当前类的类加载器
        ClassLoader classLoader = Class.forName("com.lc.内存分析.获取类加载器").getClassLoader();
        System.out.println("当前类的类加载器----->"+classLoader);

    }
}
  • 运行结果
    在这里插入图片描述
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微笑AJJD

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值