类名 | 用途 |
Class | 代表类的类型 |
Field | 代表类的字段 |
Method | 代表类的方法 |
Constructor | 代表类的构造方法 |
当 .java 文件被编译后,会生成对应的 .class 文件。开始运行后 JVM 会解读 .class 文件,解读完毕后 .class 文件会有一个对应的 java.lang.Class 类型的对象。我们可以通过反射获取到这种对象,来使用或修改属性与方法,可以在运行中改变一个类的信息,让其成为一个动态的类
获取类的相关方法(返回 Class 类型)
方法签名 | 用途 |
getClassLoader() | 获得类的加载器 |
getDeclaredClasses() | 返回类中所有的类的对象和接口的对象(包括私有) |
forName(String className) | 根据类名返回类的对象 |
newInstance() | 创建类的实例 |
getName() | 获得类的完整路径 |
获取类中字段的相关方法(返回 Field 类型)
方法签名 | 用途 |
getField(String name) | 获取公有属性字段 |
getFields() |
获取所有公有属性字段 |
getDeclaredField(String name) | 获取任一属性字段(包括私有) |
getDeclaredFields() | 获取所有属性字段(包括私有) |
获取类中注解的相关方法(返回 Annotation 类型)
方法签名 | 用途 |
getAnnotation(Class annotationClass) | 返回类中与参数类型匹配的公有注解对象 |
getAnnotation() | 返回类中所有的公有注解对象 |
getDeclaredAnnotations(Class annotationClass) | 返回类中任一与参数类型匹配的注解对象(包括私有) |
getDeclaredAnnotations() | 返回类中所有注解对象(包括私有) |
获取类中构造器的相关方法(返回 Constructor 类型)
方法签名 | 用途 |
getConstructor(Class...> parameterTypes) | 获得类中与参数类型匹配的公有构造方法 |
getConstantors() | 获得类中所有公共构造方法 |
getDeclaredConstructor(Class..> parameterTypes) | 获得类中任一与参数类型匹配的构造方法(包括私有) |
getDeclaredConstructors() | 获得类中的所有构造方法(包括私有) |
获得类中方法的相关方法(返回 Method 类型)
方法签名 | 用途 |
getMethod(String name, Class...> parameterTypes) | 获得类中与参数类型匹配的公有方法 |
getMethods() | 获得类中所有公共方法 |
getDeclaredMethod(String name, Class..> parameterTypes) | 获得类中任一与参数类型匹配的方法(包括私有) |
getDeclaredMethods() | 获得类中的所有方法(包括私有) |
Class 类提供的静态方法 forName()
使用 Class.forName("类的全路径名") 获取到返回的对应类的类对象
Class studentClass = Class.forName("Student");
每一个类都有的隐含的静态变量 class
使用 类名.class 获取到一个类对应的类对象
Class studentClass = Student.class;
每一个对象都有的方法 getClass() 继承于 Object 类
使用 实例.getClass() 获取到一个实例对应类的类对象
Student student = new Student();
Class studentClass = student.getClass();
class Student {
private String name;
private int score;
private Student(String name, int score) {
this.name = name;
this.score = score;
}
private void exam () {
System.out.println(name + " 考了 " + score + " 分");
}
private void speak (String word) {
System.out.println(name + " 说 " + word);
}
}
Class studentClass = Class.forName("Student");
注意:
凡是通过反射 Class 类得到的私有 Field、私有 Method、私有 Constructor 都需要使用 Field/Method/Constructor 对应实例中的 setAccessible() 方法来获取访问权限
通过使用反射获得的 Class 对象来获取构造方法,以得到的构造方法构造对应实例
// 获取 Student(java.lang.String, int) 构造方法
Constructor studentDeclaredConstructor =
studentClass.getDeclaredConstructor(String.class, int.class);
// 修改访问权限为允许
studentDeclaredConstructor.setAccessible(true);
// 使用 newInstance() 实例化对象
Student student =
(Student) studentDeclaredConstructor.newInstance("张三", 100);
// 测试
// 自动调用 Object 中的实例方法 toString() 获取对象对应的 hashCode
System.out.println(student);
// 获取到 name 字段
Field studentNameDeclaredField =
studentClass.getDeclaredField("name");
// 获取到 score 字段
Field studentScoreDeclaredField =
studentClass.getDeclaredField("score");
// 修改访问权限为允许
studentNameDeclaredField.setAccessible(true);
studentScoreDeclaredField.setAccessible(true);
// 测试
// 通过 Field 中的实例方法 get(instance) 获取对应实例中对应字段的值
System.out.println(studentNameDeclaredField.get(student));
System.out.println(studentScoreDeclaredField.get(student));
// 获取到 exam() 方法
Method studentExamDeclaredMethod =
studentClass.getDeclaredMethod("exam");
// 获取到 speak(java.lang.String) 方法
Method studentSpeakDeclaredMethod =
studentClass.getDeclaredMethod("speak", String.class);
// 将访问权限修改为允许
studentExamDeclaredMethod.setAccessible(true);
studentSpeakDeclaredMethod.setAccessible(true);
// 调用对应实例中的对应方法
studentExamDeclaredMethod.invoke(student);
studentSpeakDeclaredMethod.invoke(student, "反射我是真的爱");