一、反射简介(java.lang.reflect包)
Java的反射机制,在运行状态中,对于任意一个类,都能知道任意一个类的所有属性和方法。
对于任意一个对象,都能够调用它的任意一个属性和方法,这种动态获取信息以及动态调用的方式,称为Java的反射
二、Class类是所有反射操作的源头
获取class类的实例化对象,Java提供了三种获取该类对象的方式
- A、Object类中的getClass()方法 对象.getClass()
- B、Class c=类名.class
- C、Class类中的静态方法: Class.forName("包名.类名");
注意:
1、反射中所有的泛型都是?号
2、反射中的方法的方法的返回值都是Object类型
三、创建对象 newInstance()
T newInstance()方法: 创建此 Class 对象所表示的类的一个新实例。
相当于 调用类的无参构造 完成对象的创建
四、构造器对象:Constructor
1、无参构造:(字节码文件对象调用)
使用Class 类中的 newInstance()方法 创建该类对象
2、有参构造 (字节码文件对象调用)获取 public 公共构造方法(调用的有参构造必须是实体类中存在的)
使用Class类中的
- a、Constructor<T> getConstructor(Class<?>... parameterTypes) 获取此class对象的类的指定公共构造方法
- aa、 然后再使用Constructor类中的 T newInstance(Object... initargs)
- 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
五、属性:Field(字节码文件对象调用)
1.被public修饰的属性
- Field getField(String name) 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
- void set(Object obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
- Object get(Object obj) 返回指定对象上此 Field 表示的字段的值。
2.所有的属性(不能直接get,set,需要解除封装,去除权限才可)
- Field getDeclaredField(String name) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
- Field[ ] getDeclaredFields ( ) 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
- void setAccessible(boolean flag) 将此对象的 accessible 标志设置为指示的布尔值( 解除封装 去除权限 设置访问权限 true )
六、方法:Method类
1.被public修饰的方法
- Method getMethod(String name, Class<?>... parameterTypes)
- 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法
- Method类中的方法 : Object invoke(Object obj, Object... args)
- 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
2.所有的方法
- Method getDeclaredMethod(String name, Class<?>... parameterTypes)
- 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
- void setAccessible(boolean flag) 将此对象的 accessible 标志设置为指示的布尔值( 解除封装 去除权限 设置访问权限 true )
总结:
1、需要先明确获得的属性和方法的权限修饰符
2、如果为public 就用getField方法或getMethod方法获取对应的值
3、如果为private的就用
a.调用setAccess(true)方法,解除封装,去除权限
b. getDeclaredField方法,或 getDeclaredMethod方法 获取值
七、通过反射 越过泛型限定
public static void main(String[] args) throws Exception {
//通过反射 越过泛型限定
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
//list.add("abc");
//泛型 针对的是编译阶段 在运行阶段 泛型会被擦掉
System.out.println(list);
//反射 想要操作的是ArrayList类的add方法
//1.入口
Class clazz = Class.forName("java.util.ArrayList");
Method m = clazz.getMethod("add", Object.class);
m.invoke(list, "abc");
System.out.println(list);
}