Java 反射机制是一个很强大的机制,它可以让使用者能在运行的时候进行类的操作
Class testClazz = Test.getClass()
Class testClazz = Test.class
Class testClazz = Class.forName("com.test.Test")
方法 | 返回类型 | 所属类 | 解释 |
---|---|---|---|
getFields() | Field[] | java.lang.Class | 获取类中所有 public 修饰的变量 |
getDeclaredFields() | Field[] | java.lang.Class | 获取类中所有的变量 |
getField(String) | Field | java.lang.Class | 获取指定名称的变量 |
getMethods() | Method[] | java.lang.Class | 获取类中所有 public 修饰的方法 |
getDeclaredMethods() | Method[] | java.lang.Class | 获取类中所有的方法 |
getMethod(String, Class…) | Method | java.lang.Class | 获取指定名称的方法, 可以填写参数类型 |
getConstructors() | Constructor[] | java.lang.Class | 获取类中所有 public 修饰的构造器 |
getDeclaredConstructors() | Constructor[] | java.lang.Class | 获取类中所有的构造器 |
getConstructor(Class…) | Constructor | java.lang.Class | 获取指定参数类型的构造器, 参数需要填写参数类型, 如果有多个参数, 则可以填写多个参数类型 |
getAnnotations() | Annotation[] | java.lang.Class | 获取所有 public 修饰的注解 |
getDeclaredAnnotations() | Annotation[] | java.lang.Class | 获取所有的注解 |
getAnnotation(Class) | Annotation | java.lang.Class | 获取指定类型的注解, 参数中需要填写注解类型 |
getModifiers() | int | java.lang.Class | 获取所有的修饰符类型, 会返回 int 类型的值, 可以使用 Modifier.toString() 进行值的解析 |
getSuperclass() | Class | java.lang.Class | 获取父类, 如果没有继承父类, 则会返回 null |
getInterfaces() | Class[] | java.lang.Class | 获取所有的接口 |
newInstance() | T | java.lang.Class | 生成类的实例 |
在例子中,分别打印了构造器、方法、变量,从打印出来的结果来看,带 Declared 的方法会只会获取当前类所有修饰类型的方法或者变量,而不带 Declared 的方法则会获取类所有 public 的方法或者变量,包括继承的父类以及实现的接口中的 public 修饰的方法或者变量也会打印出来。
一句话总结就是:如果要找当前类以及父类和接口中的 public 的内容,则使用不带 Declared 的方法,如果要查找当前类中所有修饰符修饰的内容,则使用带 Declared 的方法。
public abstract class AbstractTest {
private String abstractField;
public Double abstractDoubleField;
public AbstractTest() {
}
abstract void abstractMethod();
private void abstractPrivateMethod() {
System.out.println("abstractPrivateMethod");
}
public void abstractPublicMethod() {
System.out.println("abstractPublicMethod");
}
}
public interface TestInterface {
String interfaceField = "接口变量";
default void interfaceDefaultMethod() {
System.out.println("interfaceMethod");
}
String interfacePublicMethod();
}
class Test extends AbstractTest implements TestInterface {
private String testName;
protected Double size;
public String testClass;
private Test() {
}
public Test(String testName, Double size) {
this.testName = testName;
this.size = size;
}
public String getTestName() {
return testName;
}
public void setTestName(String testName) {
this.testName = testName;
}
private void testMethod() {
System.out.println("测试方法");
}
public static String testPrint() {
System.out.println("打印测试方法");
return "测试";
}
@Override
void abstractMethod() {
System.out.println("abstractMethod");
}
@Override
public String interfacePublicMethod() {
System.out.println("interfacePublicMethod");
return "interfacePublicMethod";
}
}
public class ReflectionTest {
public static void main(String[] args) {
ReflectionTest test = new ReflectionTest();
System.out.println("Constructors:");
test.printConstructors(Test.class);
System.out.println("======================================");
System.out.println("DeclaredConstructors:");
test.printDeclaredConstructors(Test.class);
System.out.println("======================================");
System.out.println("Fields:");
test.printFields(Test.class);
System.out.println("======================================");
System.out.println("DeclaredFields:");
test.printDeclaredFields(Test.class);
System.out.println("======================================");
System.out.println("Methods:");
test.printMethods(Test.class);
System.out.println("======================================");
System.out.println("DeclaredMethods:");
test.printDeclaredMethods(Test.class);
}
public void printConstructors(Class<Test> clazz) {
Constructor<?>[] constructors = clazz.getConstructors();
this.constructorsPrint(constructors);
}
public void printDeclaredConstructors(Class<Test> clazz) {
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
this.constructorsPrint(constructors);
}
private void constructorsPrint(Constructor<?>[] constructors) {
for (Constructor<?> constructor : constructors) {
String constructorName = constructor.getName();
System.out.println("构造器名:" + constructorName + " {");
String modifiers = Modifier.toString(constructor.getModifiers());
System.out.print("修饰符:");
if (modifiers.length() > 0) {
System.out.print(modifiers + ";");
}
Class<?>[] parameterTypes = constructor.getParameterTypes();
System.out.print("\n" + "参数类型:");
for (Class<?> parameterType : parameterTypes) {
System.out.print(parameterType.getName() + "; ");
}
System.out.println("\n" + "}");
}
}
public void printFields(Class<Test> clazz) {
Field[] fields = clazz.getFields();
this.fieldPrint(fields);
}
public void printDeclaredFields(Class<Test> clazz) {
Field[] declaredFields = clazz.getDeclaredFields();
this.fieldPrint(declaredFields);
}
private void fieldPrint(Field[] fields) {
for (Field field : fields) {
String fieldName = field.getName();
Class<?> fieldType = field.getType();
System.out.println("变量名:" + fieldName + " {");
System.out.println("变量类型:" + fieldType);
String modifiers = Modifier.toString(field.getModifiers());
System.out.print("修饰符:");
if (modifiers.length() > 0) {
System.out.print(modifiers + ";");
}
System.out.println("\n" + "}");
}
}
public void printMethods(Class<Test> clazz) {
Method[] methods = clazz.getMethods();
this.methodPrint(methods);
}
public void printDeclaredMethods(Class<Test> clazz) {
Method[] declaredMethods = clazz.getDeclaredMethods();
this.methodPrint(declaredMethods);
}
private void methodPrint(Method[] methods) {
for (Method method : methods) {
String methodName = method.getName();
Class<?> returnType = method.getReturnType();
System.out.println("方法名:" + methodName + " {");
System.out.println("返回类型:" + returnType);
String modifiers = Modifier.toString(method.getModifiers());
System.out.print("修饰符:");
if (modifiers.length() > 0) {
System.out.print(modifiers + ";");
}
System.out.println("\n" + "}");
}
}
}
如果想要对当前类中某个使用 private 修饰的变量进行访问并设置值,会出现下面的错误,来提示无法获取 private 修饰的变量的值:
java.lang.IllegalAccessException: Class test.common.ReflectionTest can not access a member of class test.common.Test with modifiers "private"
如果想获取 private 修饰的变量的值,则需要将 Java 的安全访问控制设置为可访问,才能对私有域进行访问。
Class<? extends Test> clazz = test.getClass();
Field testName = clazz.getDeclaredField("testName");
testName.setAccessible(true);
Object testValue = testName.get(test);
System.out.println(testName + " 旧值:" + testValue);
testName.set(test, "新的 testName测试");
Object newTestValue = testName.get(test);
System.out.println(testName + " 新值:" + newTestValue);