反射是Java框架设计的灵魂
1、简介
Java反射机制的核心是在程序运行时动态加载类并获取类中各种成分,从而操作类或对象的属性和方法。
2、操作步骤
- 获取Class对象
- 获取类中各种成分
- 获取类中构造器:Constructor对象
- 获取类中成员变量:FIeld对象
- 获取类中成员方法:Method对象
- 操作对象
3、获取Class对象的三种方式
获取Class对象的三种方式:
代码实现:
Class c1 = Persion.class;
System.out.println(c1.getName()); // 全类名:com.wuyh.liaoxuefeng.Persion
System.out.println(c1.getSimpleName()); // 简名:Persion
Class c2 = Class.forName("com.wuyh.liaoxuefeng.Persion");
System.out.println(c1 == c2); // 判断是否是同一个对象。返回true
Persion p = new Persion();
Class c3 = p.getClass();
System.out.println(c2 == c3); // 判断是否是同一个对象。返回true
4、获取类中构造器
Class 提供获取类构造器的方法:
代码实现:
// 1.获取Class对象
Class c = Persion.class;
// 2.获取类中全部构造器(只能是 public 修饰),并以数组形式进行存储
Constructor[] constructors = c.getConstructors();
// 3.以遍历的形式获取类中每个构造器
for (Constructor constructor : constructors) {
// 获取构造器名称
System.out.println(constructor.getName());
// 获取构造器参数个数
System.out.println(constructor.getParameterCount());
}
// 获取类中全部构造器,并以数组形式进行存储
Constructor[] constructors1 = c.getDeclaredConstructors();
for (Constructor constructor : constructors1) {
System.out.println(constructor.getName());
}
// 获取类中某个构造器(只能是 public 修饰)
Constructor constructor1 = c.getConstructor();
System.out.println(constructor1.getName());
// 获取类中某个构造器
Constructor constructor2 = c.getDeclaredConstructor(String.class, int.class);
System.out.println(constructor2.getName());
System.out.println(constructor2.getParameterCount());
获取类中构造器的作用:依然是初始化对象返回
代码实现:
Persion p1 = (Persion) constructor1.newInstance();
System.out.println(p1);
// 构造器是 private 修饰,禁止访问
constructor2.setAccessible(true); // 暴力反射:禁止检查访问控制
Persion p2 = (Persion) constructor2.newInstance("Watson", 18);
System.out.println(p2);
5、获取类中成员变量
Class 提供获取类中成员变量的方法:
代码实现:
// 1.获取Class对象
Class c = Persion.class;
// 2.获取类中全部成员变量,并以数组形式进行存储
Field[] fields = c.getDeclaredFields();
// 3.以遍历的形式获取类中每个成员变量
for (Field field : fields) {
// 打印每个字段名称
System.out.println(field.getName());
// 打印每个字段数据类型
System.out.println(field.getType());
}
// 获取类中某个字段
Field field1 = c.getDeclaredField("name");
System.out.println(field1.getName());
// 其他 Class 提供获取类中成员变量的方法使用方法跟有以上 Class 提供获取类中构造器的方法使用方法相似,不在赘述
获取类中成员变量的作用:依然是赋值、取值
代码实现:
// 赋值
Persion p1 = new Persion();
// 字段是 private 修饰,禁止访问
fieldName1.setAccessible(true); // 暴力反射:禁止检查访问控制
fieldName1.set(p1, "Kobe");
System.out.println(p3);
// 取值
System.out.println(fieldName1.get(p1));
6、获取类中成员方法
Class 提供获取类中成员方法的API:
代码实现:
// 1.获取Class对象
Class c = Persion.class;
// 2.获取类中某个方法
Method eat_method = c.getDeclaredMethod("eat", String.class);
// 打印方法名称
System.out.println(eat_method.getName());
// 打印方法的参数个数
System.out.println(eat_method.getParameterCount());
// 打印方法返回数据类型
System.out.println(eat_method.getReturnType());
// 其他 Class 提供获取类中成员方法的方法使用方法跟有以上 Class 提供获取类中构造器的方法使用方法相似,不在赘述
获取类中成员方法的作用:依然执行
代码实现:
// 类中成员方法的执行
// 成员方法是 private 修饰,禁止访问
eat_method.setAccessible(true); // 暴力反射:禁止检查访问控制
Object rs = eat_method.invoke(p3, "air");
System.out.println(rs);
7、实例:开发简易框架
反射主要用途是 Java 框架设计,下面开发一个简易框架,用于存放对象信息:
public class ObjFrame {
// 保存任意字段信息到文件中
public static void saveObj(Object obj) throws Exception {
PrintStream ps = new PrintStream(new FileOutputStream("D:\\Code\\Java\\study\\IDEADemo\\Data\\information.txt", true));
// 1.获取Class对象
Class c = obj.getClass();
String cName = c.getSimpleName();
ps.println("----------------" + cName + "----------------");
// 2.获取类中全部成员变量,并以数组形式进行存储
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
String name = field.getName();
field.setAccessible(true);
String value = field.get(obj) + "";
ps.println(name + ":" + value);
}
ps.close();
}
}