Java 反射
获取类的Class对象3种方法:
Class clazz = Class.forName("Animal");
Class clazz = User.class;
User user = new User(); Class clazz = user.getClass();
1 获取并使用构造方法
getConstructor(Class<?>... paramTypes)
:获取单个 public 构造(参数类型匹配)getDeclaredConstructor(Class<?>... paramTypes)
:获取单个任意权限构造(含 private)getConstructors()
:获取所有 public 构造(返回Constructor[]
数组)getDeclaredConstructors()
:获取所有构造(含 private,返回Constructor[]
数组)
// 01:公共方法无参构造
public User() {
}
// 公共方法有参构造
public User(String name) {
this.name = name;
}
// 02:私有方法有参构造
private User(String name, int age) {
this.name = name;
this.age = age;
}
// 先获取类Class对象
Class<User> userClazz = User.class;
// 根据参数类型匹配,获取公共方法无参构造对象,参数null可省略
Constructor<User> constructor = userClazz.getConstructor();
// 利用构造器创建对象
User user1 = constructor.newInstance();
// 获取私有方法有参构造,根据参数类型来匹配。
Constructor<User> privateConstructor = userClazz.getDeclaredConstructor(String.class, int.class);
// 绕过权限检查(关键!否则抛IllegalAccessException)
privateConstructor.setAccessible(true);
// 调用构造器创建对象(传入实际参数)
User user2 = privateConstructor.newInstance("张三", 20);
// 获取所有公共构造
Constructor[] constructors = userClazz.getConstructors();
// 获取所有任意权限构造
Constructor[] allDeclaredConstructors = studentClass.getDeclaredConstructors();
2 get/set成员变量
getField(String name)
:获取单个 public 成员变量(含父类继承的)getDeclaredField(String name)
:获取单个本类任意权限成员变量(不含父类)getFields()
:获取所有 public 成员变量(返回Field[]
)getDeclaredFields()
:获取所有本类成员变量(含 private,返回Field[]
)- Type 实例对象变量值 = (Type) Class变量字段.get(实例对象)
- Class变量字段.set(实例对象, 新值)
// 利用之前获取的构造器,创建对象
User user2 = privateConstucotr.newInstance("张三",20);
// 获取Class对象的变量
Field nameField = userClazz.getField("name");
String oldName = (String) nameField.get(user2);
nameField.set(user2, "李四");
// 操作私有变量,需要绕过权限
Field ageField = userClazz.getDeclaredField("age");
ageField.setAccessible(true); // 关闭访问检查
int oldAge = (int) ageField.get(user2);
ageField.set(user2, 25);
int newAge = (int) ageField.get(user2);
3 get并调用成员方法
getMethod(String name, Class<?>... paramTypes)
:获取单个 public 方法(含父类继承的)getDeclaredMethod(String name, Class<?>... paramTypes)
:获取单个本类任意权限方法(含 private)getMethods()
:获取所有 public 方法(含Object
类继承的,返回Method[]
)getDeclaredMethods()
:获取所有本类方法(含 private,返回Method[]
)
注意获取Method时要带参数来匹配。
静态方法属于类,不属于实例对象,因此invoke()的第一个参数应该传null。
// 1. public无参方法
public void showInfo() {
System.out.println("姓名:" + name + ",年龄:" + age);
}
// 2. private有参方法(参数为String)
private String sayHello(String target) {
return "Hello, " + target;
}
// 3. public静态方法(参数为int,返回int)
public static int add(int a, int b) {
return a + b;
}
Method showInfoMethod = userClazz.getMethod("showInfo");
// 执行实例对象的方法:invoke(对象实例, 参数);(无参null可省略)
showInfoMethod.invoke(user2);
// 私有方法,绕过检查
Method sayHelloMethod = userClazz.getDeclaredMethod("sayHello");
sayHelloMethod.setAccessible(true);
String result = (String) sayHelloMethod.invoke(user2, "Hello");
System.out.println(result);
Method addMethod = userClazz.getMethod("add", int.class, int.class);
int sum = (int) addMethod.invoke(null, 10, 20);
System.out.println(sum);
利用反射,实现通用对象数据保存
public static void saveObject(Object obj) throws Exception {
// 1. 获取Class对象
Class<?> clazz = obj.getClass();
System.out.println("=====" + clazz.getSimpleName() + "对象数据=====");
// 2. 获取所有成员变量(含private)
Field[] fields = clazz.getDeclaredFields();
// 3. 遍历变量并输出
for (Field field : fields) {
// 绕过权限检查
field.setAccessible(true);
// 获取变量名
String fieldName = field.getName();
// 获取变量值(需传入对象实例)
Object fieldValue = field.get(obj);
// 格式化输出
System.out.println(fieldName + " = " + fieldValue);
}
}
// 测试:传入User对象和Book对象(自定义Book类含name、price)
public static void main(String[] args) throws Exception {
User user = new User("王五", 30);
Book book = new Book("Java反射", 59.9);
saveObject(user); // 输出User的name和age
saveObject(book); // 输出Book的name和price
}
分类:
Java-Backend
标签:
Java
版权申明
本文系作者 @xiin 原创发布在To Future$站点。未经许可,禁止转载。
暂无评论数据