反射本质就是操作构造方法、成员变量、成员方法
反射的基本理解:
利用另一种方式去获取一个类的对象、调用类中的方法、使用类中的成员变量。
反射是基于正射。
正射: 对象.方法(实际参数)
反射: 方法对象.invoke(对象,实际参数)反射代码的编写:
1、获取一个类的字节码对象 -> Class 类的类
字节码对象中封装了类中的构造方法、成员变量、成员方法
2、根据字节码对象获取类中相应的成员对象
根据字节码对象获取类中 构造方法的对象 -> Constructor
根据字节码对象获取类中 成员方法的对象 -> Method
根据字节码对象获取类中 成员变量的对象 -> Field
3、根据不同的成员对象完成不同的功能
构造方法对象 -> 创建此类的对象
成员变量对象 -> 赋值、获取值
成员方法对象 -> 调用方法
获取一个类的字节码对象的三种方法:
1、对象.getClass() -> 这个对象所在类的字节码对象
Class getClass():来自Object类
2、类型.class -> 类型的名称.class 可以获取到此类型的字节码对象
Class clazz = String.class;
Class clazz = int.class;
Class clazz = Student.class;
3、Class.forName("类的全类名"); -> 通过一个Class的静态方法获取一个类的字节码对象
Class clazz = Class.forName("java.lang.String");
Class clazz = Class.forName("com.itheima.Student");
根据字节码对象获取类中的成员:
构造方法:
获取一个类中的构造方法对象的方法来自于Class类:
Constructor[] getConstructors():获取一个类中所有被public修饰的构造方法对象
Constructor getConstructor(Class...parameterTypes):获取一个类中指定的被public修饰的构造方法对象
🚩 Declared:忽视修饰符
Constructor[] getDeclaredConstructors():获取一个类中所有的构造方法对象
Constructor<T> getDeclaredConstructor(Class... parameterTypes):获取一个类中指定的构造方法对象
Class类中有一个快捷的生成一个类无参构造方法对象的方法
T newInstance():根据无参构造快速的创建一个该类的对象
来自于 Constructor 类的方法 来实现对象创建
T newInstance(Object...initargs)
Object...initargs:启动此构造方法时需要传入的实际参数
T: 你创建出来的这个对象
若要去访问类中私有成员,你必须使用成员对象开启暴力反射开关。两种创建此类对象的方法
1、有字节码对象 --> 根据字节码对象获取相应的构造方法对象 --> 此构造方法对象调newInstance方法创建该类对象
(private修饰的构造方法记得打开暴力反射开关)
2、有字节码对象 --> 直接调用Class类中的newInstance方法创建该类的无参对象成员变量:
1、获取一个类的字节码对象
2、获取一个类中成员变量对象的方法来自于Class类
Field[] getDeclaredFields():获取一个类中所有的成员变量对象
Field getDeclaredField(String name):获取一个类中指定的成员变量对象
String name:变量的名字
3、赋值和取值 --> 来自于Field类
Object get(Object obj):取值
Object obj:哪一个对象的
void set(Object obj, Object value):赋值
Object obj:哪一个对象的
Object value:你要把这个参数的值设置为多少⚠️: 当成员变量被私有,必须在使用前开启暴力反射
成员方法:
1、获取一个类的字节码对象
2、获取一个类中成员方法对象的方法来自于Class类
Method[] getDeclaredMethods():获取一个类中所有的成员方法对象
Method getDeclaredMethod(String name, Class... parameterTypes):获取一个类中指定的成员方法对象
String name:方法名 -> 写方法名字的时候不要加()
Class...parameterTypes:方法形式参数数据类型的字节码对象
3、有了方法对象 你就想启动方法 启动方法的方法在Method类中
Object invoke(Object obj, Object... args):启动方法
Object obj:具体调用方法的对象
Object... args:启动方法需要你传入的实际参数
Object:
如果方法有返回值:invoke方法的返回值就是用来接受调用方法的返回值的
如果方法没有返回值:invoke方法的返回值就是null注意:
1、启动方法 如果启动的是无返回值的方法就直接调用invoke
2、因为启动的方法有返回值 所以调用invoke方法的时候记得接受调用
3、私有方法在启动之前记得开启暴力反射开关
如果成员是私有的需要开启暴力反射:获取的成员.setAccessible(true);
下面附图总结一下: