反射

Java 反射(Reflection)

反射(Reflection)是 Java 提供的强大机制,允许程序在运行时动态获取类的信息操作类的属性和方法(包括私有、继承的成员)。它广泛应用于框架(如 Spring、Hibernate)、动态代理、测试工具等场景。


1. 反射的核心类

说明
Class<T> 表示一个类或接口,反射的入口
Field 表示类的成员变量(属性)
Method 表示类的方法
Constructor 表示类的构造方法

2. 获取 Class 对象的 3 种方式

// 方式1:类名.class
Class<?> clazz1 = String.class;

// 方式2:对象.getClass()
String str = "Hello";
Class<?> clazz2 = str.getClass();

// 方式3:Class.forName("全限定类名")
Class<?> clazz3 = Class.forName("java.lang.String");

3. 常用方法

(1)Class

方法 说明
clazz.getName()clazz.getCanonicalName() 获取类全限定名
区别:如果是内部类,这俩方法返回不一样
clazz.getSimpleName() 获取类名
clazz.isInterface() 是否是接口
clazz.getInterfaces() 获取所有实现的接口
clazz.getSupercalss() 获取父类
直接父类,爷爷辈获取不了
clazz.newInstance() 使用无参构造创建实例
没有无参构造会报错
clazz.getFields()clazz.getField(字段名)
clazz.getDeclaredFields()clazz.getDeclaredField(字段名)
获取成员变量
带 Declared:能获取私有,但不包括继承
不带 Declared:只能获取 public,但包括继承
clazz.getMethods()clazz.getMethod(方法名, 可变参数)
clazz.getDeclaredMethods()clazz.getDeclaredMethod(方法名, 可变参数)
获取成员方法
同上,也根据 Declared 分为两组
参数是可变参数,可传任意类型的 Class 比如:
clazz.getMethod("draw", int.class, String.class)

(2)Field

方法 说明
setAccessible(true) 私有变量可访问(方法也适用)
set(目标对象, 值) 修改变量的值
对于 final 字段不会报错,但实际上该字段的值不会改变
get(目标对象) 获取变量的值
getName() 获取属性名称
getType() 获取属性类型
也是一个 Class 对象
isEnumConstant() 属性是否是枚举

(3)Method

方法
invoke(目标对象, 可变参数) 执行方法
getReturnType() 获取方法返回值类型
是一个 Class 对象

4. 示例

(1)获取并操作属性(包括私有属性)

import java.lang.reflect.Field;

class Person {
    private String name;
    public int age;
}

public class Main {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Person.class;
        Person person = new Person();

        // 获取public属性
        Field ageField = clazz.getField("age");
        ageField.set(person, 25);  // 设置值
        System.out.println(ageField.get(person));  // 获取值

        // 获取private属性(需设置可访问性)
        Field nameField = clazz.getDeclaredField("name");
        nameField.setAccessible(true);  // 解除私有限制
        nameField.set(person, "Alice");
        System.out.println(nameField.get(person));
    }
}

(2)调用方法(包括私有方法)

import java.lang.reflect.Method;

class Calculator {
    private int add(int a, int b) {
        return a + b;
    }
    public int multiply(int a, int b) {
        return a * b;
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Calculator.class;
        Calculator calc = new Calculator();

        // 调用public方法
        Method multiplyMethod = clazz.getMethod("multiply", int.class, int.class);
        int result = (int) multiplyMethod.invoke(calc, 3, 4);  // 12

        // 调用private方法
        Method addMethod = clazz.getDeclaredMethod("add", int.class, int.class);
        addMethod.setAccessible(true);
        int sum = (int) addMethod.invoke(calc, 2, 3);  // 5
    }
}

(3)操作继承的属性和方法

class Parent {
    protected String familyName = "Smith";
}

class Child extends Parent {
    private String nickname = "Tom";
}

public class Main {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Child.class;
        Child child = new Child();

        // 获取继承的protected属性
        Field familyNameField = clazz.getSuperclass().getDeclaredField("familyName");
        familyNameField.setAccessible(true);
        System.out.println(familyNameField.get(child));  // Smith

        // 获取子类私有属性
        Field nicknameField = clazz.getDeclaredField("nickname");
        nicknameField.setAccessible(true);
        System.out.println(nicknameField.get(child));  // Tom
    }
}
posted @ 2023-03-01 18:09  CyrusHuang  阅读(31)  评论(0)    收藏  举报