本文已参与「新人创作礼」活动,一起开启掘金创作之路。
反射
反射是指对于任何一个 Class
类,在运行的时候 都可直接得到这个类的全部成分。
在运行时,可以直接得到这个类的构造器对象:Constructor
在运行时,可以直接得到这个类的成员变量对象:Field
在运行时,可以直接得到这个类的成员方法对象:Method
这种运行时动态获取类信息以及动态调用类中成分的能力 称为Java语言的反射机制。
- 反射获取类对象
public static void main(String[] args) throws Exception {
// class类中的静态方法
Class<?> c = Class.forName("com.Review.day12.d2_getClass.Student"); // forName(权限名:包名+类名)
System.out.println(c); // class com.Review.day12.d2_getClass.Student
// 类名.class
Class<Student> c1 = Student.class;
// 对象.getClass() 获取对象对应类的class对象
Student s = new Student();
System.out.println(s.getClass());
}
- 反射获取构造器对象
// getConstructor 不能拿私有的 只能拿 public修饰的
@Test
public void getConstructor() throws Exception {
// 获取类对象
Class c = Student.class;
// 提取类的全部构造器 用数组装[2]
Constructor[] Constructor = c.getConstructors();
// 遍历构造器
for (java.lang.reflect.Constructor constructor : Constructor) {
// constructor.getParameterCount() 获取参数个数
System.out.println(constructor.getName() + "====>" + constructor.getParameterCount());
}
}
// getDeclaredConstructors 私有的也可以拿
// getConstructor 获取public修饰的某个构造器 -- 定位单个
// getDeclaredConstructor 获取某个构造器(无论私有还是公开) - 定位单个 - 常用
******暴力破解
// 获取类对象
Class c = Student.class;
Constructor cons = c.getDeclaredConstructor();
// 如果遇到了私有的构造器,可以暴力反射 - 我理解为暂时破坏单例设计模式
cons.setAccessible(true) // 权限暂时被打开
// 接着就可以通过 私用的构造器创建对象了
Student s = (Student) cons.newInstance();
- 反射获取成员变量对象
public static void main(String[] args) {
// 获取Class对象
Class c = Student.class;
// 定位全部成员变量
Field[] fields = c.getDeclaredFields();
// 遍历
for (Field field : fields) {
// field.getType() 获取类型
System.out.println(field.getName() + "====>" + field.getType()); // name====>class java.lang.String
}
}
// getDeclareField 根据名称定位某个成员变量
// 成员变量同样可以进行 暴力破解
- 反射获取方法对象
public static void main(String[] args) {
// 反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。
// class类中用于获取成员方法的方法。
Class c = Student.class;
// 获得类中的所有成员方法对象,返回数组,只获得本类中申明的方法。
Method[] dcl = c.getDeclaredMethods();
for (Method method : dcl) {
System.out.println(method.getName() + " 返回值类型" + method.getReturnType() +
" 参数个数:" + method.getParameterCount());
}
}
// 提取单个方法对象 getDeclaredMethod
- 反射的作用 - 泛型擦除
public static void main(String[] args) throws Exception {
// 声明两个字典
ArrayList<Integer> list1 = new ArrayList<>();
ArrayList<String> list2 = new ArrayList<>();
System.out.println(list1.getClass());
System.out.println(list2.getClass());
System.out.println(list1.getClass() == list2.getClass());
System.out.println("__________________");
ArrayList list3 = list2; // 这种也是一种泛型擦除
list1.add(1);
list1.add(2);
list1.add(3);
Class c = list1.getClass();
// 定义c类中的add方法
Method add = c.getDeclaredMethod("add", Object.class);
Object laity = add.invoke(list1, "laity");
System.out.println(laity);
System.out.println(list1); // [1, 2, 3, laity]
}