【Java 基础】Java 反射使用方法简介



文章目录

  • 【Java 基础】Java 反射使用方法简介
  • 一、反射简介
  • 1. 获取 Class 的方法
  • 2. Class 类常用方法解释
  • 3. 例子
  • 【1】获取类中所有构造器、方法、变量
  • 【2】访问并设置 private 修饰的变量值



一、反射简介

Java 反射机制是一个很强大的机制,它可以让使用者能在运行的时候进行类的操作

1. 获取 Class 的方法

  1. getClass() 方法
Class testClazz = Test.getClass()
  1. 类名.class
Class testClazz = Test.class
  1. Class.forName() 方法
Class testClazz = Class.forName("com.test.Test")

2. Class 类常用方法解释

方法

返回类型

所属类

解释

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

生成类的实例

3. 例子

【1】获取类中所有构造器、方法、变量

在例子中,分别打印了构造器、方法、变量,从打印出来的结果来看,带 Declared 的方法会只会获取当前类所有修饰类型的方法或者变量,而不带 Declared 的方法则会获取类所有 public 的方法或者变量,包括继承的父类以及实现的接口中的 public 修饰的方法或者变量也会打印出来。

一句话总结就是:如果要找当前类以及父类和接口中的 public 的内容,则使用不带 Declared 的方法,如果要查找当前类中所有修饰符修饰的内容,则使用带 Declared 的方法。

  • AbstractTest.java
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");  
    }  
}
  • TestInterface.java
public interface TestInterface {  
  
    String interfaceField = "接口变量";  
  
    default void interfaceDefaultMethod() {  
        System.out.println("interfaceMethod");  
    }  
  
    String interfacePublicMethod();  
}
  • Test.java
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";  
    }  
}
  • ReflectionTest.java
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" + "}");  
        }  
    }  
}

【2】访问并设置 private 修饰的变量值

如果想要对当前类中某个使用 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);