视频讲解地址:https://www.bilibili.com/video/BV1Rx41197TC?from=search&seid=16603952049666504496
反射到底是什么意思?提出的目的是什么?
反射机制:Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。(就好比去医院拍CT或者其余的放射科,拍完后就能看到你整个人的具体架构,那么我们说的这个反射是通过什么去映射类呢?就是通过类的字节码文件,也就是class文件,通过class文件可以得到类的成员属性,类的构造方法,类的成员方法,相当于我们知道了类的内部构造)
当class文件被jvm加载到虚拟机内存后,就将其转换为一个的java.lang.Class对象实例,也就是说每一个字节码文件被加载后都变成了一个Class对象,通过这个对象可以获得对应类中的构造方法,成员变量,成员方法
所以要想实现反射,就得先获取到字节码对象(相当于CT片)
获取某个类的字节码对象的方式一(通过每个类从object继承到的getClass()方法)
获取某个类的字节码对象的方式二(通过每个类的class属性)
获取字节码对象的方式三(最常用的方法,Class类的静态方法forName)
上面已经讲了获取字节码对象的三种方法,可以看到每种方法获取的同一个类的字节码对象都是一样的,创建完字节码对象后,也就是拍好CT片后,如何通过字节码对象来反射目标类(所以要先知道这个字节码对象中包含哪些东西,也就是我们通过字节码文件可以得到目标类中的哪些东西)
一 使用字节码对象得到构造方法对象(Constructor),然后创建类对象
先定义一个实体类Person:
Package reflex;
public class Person {
//私有属性
private String name = "Tom";
//公有属性
public int age = 18;
//构造方法1
public Person() {
}
//构造方法2
public Person(String name,int age){
}
//私有方法
private void say(){
System.out.println("private say()...");
}
//公有方法
public void work(){
System.out.println("public work()...");
}
}
①批量得到所有的public构造器包括父类中定义的,用getConstructors() 注意这个得不到类定义的private构造方法,我们下面也会讲到如何获取类中定义非public的构造方法
②批量获取所有的构造方法getDeclaredConstructors() 因为getConstructors()只能获取类中的public构造方法,获取不到其友好的,受保护的,私有的构造方法,所以引入了getDeclaredConstructors()
③获取某个构造器,这里用的是getConstructor(参数列表),不同于上面的带‘S’的构造器,注意里面的参数列表是根据类里定义的构造方法的参数来决定的,只不过这里传的参数是对应类型的字节码对象
1 getConstructor(参数列表) 这个方法可以获得类中声明的所有public构造器中的一个,具体是哪个根据参数列表来决定
2 getDeclaredConstructor(参数列表)这个方法可以获得类中声明的所有构造器中的一个,具体是哪个根据参数列表来决定
注意:字节码对象为我们提供了另一种快速创建对象的方法,不用先获取构造器对象,然后再创建类对象(底层调用的是类的无参构造方法,所以类中必须有无参构造方法),也就是说
Object newInstance=class.newInstance() 相当于下面的两句
Constructor constructor =class.getConstructor();
Object newInstance=constructor.getInstance();
二 通过字节码对象得到成员方法对象(Method)
获取方法对象和获取构造器的方法用法都一样,有四个方法getMethods getDeclaredMethods getMethod getDeclaredMethod(用法对应于上面讲的getConstructors getDeclaredConstructors getConstructor getDeclaredConstructor)
上面的构造器创建后,创建对象用getInstance,这个方法对象创建了,如何执行呢,用的是invoke(类对象,参数)
注意:getMethods,getMethod 可以获取到类中定义的public方法,以及父类中定义的public方法
getDeclaredMethods,getDeclaredMethod 可以获取到类中定义的全部方法,但是获取不到父类中的方法
三 通过字节码对象得到成员字段对象(Field)
获取成员字段对象和获取成员方法用法都一样,有四个方法getFields getDeclaredFields getField getDeclaredField
得到成员变量对象后 如何使用呢,用set(对象,参数)