反射 refection

反射机制 refection

运行时加载、探知、使用编译期间完全未知的类
程序在运行状态中,动态加载一个只要名称的类,对于任意一个已加载的类,都能知道这个类的所有属性和方法,对于任意一个对象,都能够调用其的方法和属性
加载完类之后,在堆内存中,将产生一个Class类型的对象,这个对象包含了完整的类的结构信息,可以通过这个对象查看类的结构,称为反射

作用:

  • 动态加载类、获取类的属性、方法、构造器
  • 动态构造对象
  • 动态调用类和对象的任意方法、构造器
  • 动态调用和处理属性
  • 获取泛型信息
  • 处理注解
Class c = Class.forName("com.test.User");
@Test
public void reflection() throws Exception {
    String path = "annotation.Student";

    /******************************
     *
     * 一个类被加载后,JVM就会创建一个对应类的Class,且一个类只对应一个Class
     * 所以 clazz 和 clazz2 hashCode相同
     *
     * */
    Class<?> clazz = Class.forName(path);
    System.out.println(clazz.hashCode()); // - 254413710

    Class<?> clazz2 = Class.forName(path);
    System.out.println(clazz2.hashCode()); // - 254413710

    /******************************/

    System.out.println(clazz.getName()); // - annotation.Student - 含包名
    System.out.println(clazz.getSimpleName()); // - Student

    Field[] publicField = clazz.getFields(); // - 获取 public 的 field
    Field[] addField = clazz.getDeclaredFields(); // - 获取所有的 field

    Method[] methods = clazz.getDeclaredMethods(); // - 获取所有方法
    clazz.getDeclaredMethod("getName", null); // - 方法无参,null
    clazz.getDeclaredMethod("setName", String.class); // - 方法有参,传入参数类型的class

    Constructor<?>[] constructors = clazz.getDeclaredConstructors(); // - 获取构造器
    Constructor<?> constructor = clazz.getDeclaredConstructor(null);

    /******************************/

    /**
     * 通过反射API调用
     * */
    Student o = (Student) constructor.newInstance(null);
    Method setName = clazz.getDeclaredMethod("setName", String.class);
    setName.invoke(o, "小小白");
    System.out.println(o.getName());
}

反射操作泛型 Generic

java采用泛型擦除机制引入泛型,在Java中的泛型只是给编译器Javac使用的,是确保数据的安全性和免去强制类型转换的麻烦。class文件编译完成后,所有和泛型有关的类型将全部擦除
为了通过反射操作这些类型以迎合实际开发的需要,Java新增了ParameterizedType、GenericArrayType、TypeVariable、WildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型

**ParameterizedType:**表示参数化的类型,Collection<String>
**GenericArrayType:**表示一种元素类型是参数化类型或者类型变量的数组类型
**TypeVariable:**是各种类型变量的公共父接口
**WildcardType:**代表一种通配符类型表达式,? extends Number

反射机制性能问题

setAccessible
启用和禁用访问安全检查的开关,值为 true ,则指示反射的对象在使用时应该取消 Java 语言访问检查。false 则指示反射的对象应该实施 Java 语言访问检查
当禁止安全检查时,可以大大提高反射的运行速度

public Map<Integer, Student> reflectionTest(List<Student> list) {
    return null;
}

@Test
public void reflectionTest() throws Exception {
    /**
     * 获取方法参数泛型
     * */
    Method method = TestClass.class.getMethod("reflectionTest", List.class);
    Type[] type = method.getGenericParameterTypes();
    for (Type t : type) {
        System.out.println("---" + t); // - java.util.List<annotation.Student>
        if (t instanceof ParameterizedType) {
            Type[] typeArguments = ((ParameterizedType) t).getActualTypeArguments();
            for (Type typeArgument : typeArguments) {
                System.out.println("泛型类型:" + typeArgument);  // - class annotation.Student
            }
        }
    }

    /**
     * 获取方法返回值泛型
     * */
    Type returnType = method.getGenericReturnType();
    if (returnType instanceof ParameterizedType) {
        Type[] arguments = ((ParameterizedType) returnType).getActualTypeArguments();
        for (Type a : arguments) {
            System.out.println("返回值泛型类型:" + a);
            // - 返回值泛型类型:class java.lang.Integer
            // - 返回值泛型类型:class annotation.Student
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值