文章目录
Java 反射
反射可以在不修改源代码的情况下,通过配置文件动态控制程序的运行
前期准备
先准备一个 Person 类, 以及 Person 的父类 Human
class Human {
public String address = "上海";
public Human() {
}
public void sport() {
}
}
class Person extends Human{
public int age = 10;
private String name = "张三";
public static String phonenum = "12345";
public Person() {
}
public Person (int age) {
this.age = age;
}
private Person(int age, String name) {
this.age = age;
this.name = name;
}
private int getAge(int myAge) {
return myAge;
}
public String getName() {
return name;
}
public static void hi() {
System.out.println("hello");
}
@Override
public String toString() {
return "Person{" + "age=" + age + ", name='" + name + '\'' + '}';
}
}
1. 反射创建对象
方法一:使用class对象创建
// 这里写你们自己的类的全路径
Class<?> personCls = Class.forName("com.example.demo.Person");
// newInstance创建一个person对象
Object person = personCls.newInstance();
方法二:使用 public 构造器创建
// 获取当前类指定的 public 构造器,根据你传的参数类型寻找构造器这里找到的就是 public Person (int age)
Constructor<?> constructor = personCls.getConstructor(int.class);
Object person = constructor.newInstance(18);
方法三:使用 private 构造器创建
// 获取当前类指定的构造器,根据你传的参数类型寻找构造器这里找到的就是 private Person(int age, String name)
Constructor<?> declaredConstructor = personCls.getDeclaredConstructor(int.class, String.class);
Object person = declaredConstructor.newInstance(18, "李四");
2. 反射获取类构造器
// 获取当前类所有 public 构造器,父类的构造器无法获取
Constructor<?>[] constructors = personCls.getConstructors();
// 获取当前类所有构造器,private 也可以获取到
Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
// 获取当前类指定的 public 构造器,根据你传的参数类型寻找构造器这里找到的就是 public Person (int age)
Constructor<?> constructor = personCls.getConstructor(int.class);
// 获取当前类指定的构造器,根据你传的参数类型寻找构造器这里找到的就是 private Person(int age, String name)
Constructor<?> declaredConstructor = personCls.getDeclaredConstructor(int.class, String.class);
3. 反射获取字段
// 获取类的class对象
Class<?> personCls = Class.forName("com.example.demo.Person");
// 创建一个person对象
Object person = personCls.newInstance();
3.1 获取 public 字段
// 可以获取当前类和父类的public字段
Field address = personCls.getField("address");
// 打印address的值,get时需要传入一个创建好的person对象
System.out.println(address.get(person));
3.2 获取 private 字段
// 可以获取当前类的所有字段包括 private
Field name = personCls.getDeclaredField("name");
// 注意:由于name字段是 private 所以想要获取到name的值需要 setAccessible(true)
name.setAccessible(true);
System.out.println(name.get(person));
3.3 获取静态字段
Field phonenum = personCls.getField("phonenum");
// 注意获取静态字段时 get 方法可以传入 null,不需要传入一个创建好的person对象
System.out.println(phonenum.get(null));
4. 反射执行类方法
4.1 执行 public 方法
// 获取本类和父类中 public 的方法
Method sport = personCls.getMethod("sport");
// 需要传入一个创建好的 person 对象
sport.invoke(person);
4.2 执行 private 方法
// 获取本类所有的方法包括 private, 方法有参数时需要传入参数的类型
Method getAge = personCls.getDeclaredMethod("getAge", int.class);
// 注意:由于时private 方法需要setAccessible(true)
getAge.setAccessible(true);
// 传入创建好的person对象及参数
getAge.invoke(person, 18);
4.3 执行静态方法
Method hi = personCls.getMethod("hi");
// 注意:由于是静态方法所以不需要传入person对象传入 null 即可
hi.invoke(null);