java反射
字数 3572 2025-08-24 07:48:22

Java反射机制详解

一、反射概念

Java反射是指在程序运行期间对于类的属性、方法、构造方法等进行动态访问和操作的机制。通过Java反射API,程序能够在运行期获取类的信息,操作类的属性、方法、构造方法,创建类的对象等。

核心特点:不适用new创建对象而访问类中方法的过程即可成为反射。

二、反射相关包

Java反射的相关类位于 java.lang.reflect.* 包中。

三、反射的作用

  1. 获取任意类的名称、package信息、所有属性、方法、注解、类型、类加载器等
  2. 获取任意对象的属性,并且能改变对象的属性
  3. 调用任意对象的方法
  4. 判断任意一个对象所属的类
  5. 实例化任意一个类的对象
  6. 实现动态装配,降低代码的耦合度,动态代理等

四、核心反射类

  1. java.lang.Class:代表整个字节码,代表一个类型,代表整个类
  2. java.lang.reflect.Method:代表字节码中的方法字节码,代表类中的方法
  3. java.lang.reflect.Constructor:代表字节码中的构造方法字节码,代表类中的构造方法
  4. java.lang.reflect.Field:代表字节码中的属性字节码,代表类中的成员变量(静态变量+实例变量)

注意:必须先获取Class才能获取Method、Constructor、Field。

五、获取Class实例的三种方法

  1. Class.forName("完整类名带包名")

    Class<?> cls = Class.forName("java.util.ArrayList");
    
  2. 对象.getClass()

    Object obj = new String("Hello World");
    Class<? extends Object> objClass = obj.getClass();
    
  3. 类名.class

    Class<String> strClass = String.class;
    

六、Class类常用方法

方法 描述
getFields() 获得类的public类型的属性
getDeclaredFields() 获得类的所有属性
getField(String name) 获得类的指定属性
getMethods() 获得类的public类型的方法
getMethod(String name, Class[] args) 获得类的指定方法
getConstrutors() 获得类的public类型的构造方法
getConstrutor(Class[] args) 获得类的特定构造方法
newInstance() 通过类的无参构造方法创建对象
getName() 获得类的完整名字
getPackage() 获取此类所属的包
getSuperclass() 获得此类的父类对应的Class对象

七、通过反射实例化对象

  1. 基本方法:

    对象.newInstance()
    

    注意:没有公共的无参构造函数,newInstance()方法就会抛出InstantiationException异常

  2. 使用特定构造函数:

    Class<MyClass> cls = MyClass.class;
    Constructor<MyClass> constructor = cls.getDeclaredConstructor(int.class, String.class);
    MyClass myObj = constructor.newInstance(42, "Hello");
    

八、Class.forName导致类加载

如果只是希望一个类的静态代码块执行,其它代码一律不执行,可以使用:

Class.forName("完整类名");

这个方法的执行会导致类加载,类加载时,静态代码块执行。

九、反射Field(反射/反编译一个类的属性)

Class类相关方法:

  • public T newInstance():创建对象
  • public String getName():返回完整类名带包名
  • public String getSimpleName():返回类名
  • public Field[] getFields():返回类中public修饰的属性
  • public Field[] getDeclaredFields():返回类中所有的属性
  • public Field getDeclaredField(String name):根据属性名name获取指定的属性
  • public native int getModifiers():获取属性的修饰符列表,返回的修饰符是一个数字
  • public Method[] getDeclaredMethods():返回类中所有的实例方法
  • public Method getDeclaredMethod(String name, Class<?>... parameterTypes):根据方法名name和方法形参获取指定方法
  • public Constructor<?>[] getDeclaredConstructors():返回类中所有的构造方法
  • public Constructor getDeclaredConstructor(Class<?>... parameterTypes):根据方法形参获取指定的构造方法
  • public native Class<? super T> getSuperclass():返回调用类的父类
  • public Class<?>[] getInterfaces():返回调用类实现的接口集合

Field类方法:

  • public String getName():返回属性名
  • public int getModifiers():获取属性的修饰符列表
  • public Class<?> getType():以Class类型,返回属性类型
  • public void set(Object obj, Object value):设置属性值
  • public Object get(Object obj):读取属性值

给属性赋值和读取:

  1. 直接赋值:

    对象.属性 = ;
    对象.属性;
    
  2. 通过反射赋值:

    属性.set(对象, );
    属性.get(对象);
    

示例代码:

class ReflectTest07 {
    public static void main(String[] args) throws Exception {
        // 不使用反射机制给属性赋值
        Student student = new Student();
        student.no = 1111;
        System.out.println(student.no);
        
        // 使用反射机制给属性赋值
        Class studentClass = Class.forName("javase.reflectBean.Student");
        Object obj = studentClass.newInstance();
        Field noField = studentClass.getDeclaredField("no");
        noField.set(obj, 22222);
        System.out.println(noField.get(obj));
    }
}

十、反射Method(反射/反编译一个类的方法)

Method类方法:

  • public String getName():返回方法名
  • public int getModifiers():获取方法的修饰符列表
  • public Class<?> getReturnType():以Class类型,返回方法类型
  • public Class<?>[] getParameterTypes():返回方法的修饰符列表
  • public Object invoke(Object obj, Object... args):调用方法

调用方法:

方法.invoke(对象, 实参);

示例代码:

class ReflectTest10 {
    public static void main(String[] args) throws Exception {
        // 不使用反射机制调用方法
        UserService userService = new UserService();
        System.out.println(userService.login("admin", "123") ? "登入成功!" : "登入失败!");
        
        // 使用反射机制调用方法
        Class userServiceClass = Class.forName("javase.reflectBean.UserService");
        Object obj = userServiceClass.newInstance();
        Method loginMethod = userServiceClass.getDeclaredMethod("login", String.class, String.class);
        Object resValues = loginMethod.invoke(obj, "admin", "123");
        System.out.println(resValues);
    }
}

十一、反射Constructor(反射/反编译一个类的构造方法)

Constructor类方法:

  • public String getName():返回构造方法名
  • public int getModifiers():获取构造方法的修饰符列表
  • public Class<?>[] getParameterTypes():返回构造方法的修饰符列表
  • public T newInstance(Object ... initargs):创建对象

示例代码:

class ReflectTest12 {
    public static void main(String[] args) throws Exception {
        // 不使用反射创建对象
        Vip vip1 = new Vip();
        Vip vip2 = new Vip(123, "zhangsan", "2001-10-19", false);
        
        // 使用反射机制创建对象
        Class vipClass = Class.forName("javase.reflectBean.Vip");
        // 调用无参数构造方法
        Object obj1 = vipClass.newInstance();
        System.out.println(obj1);
        
        // 调用有参数的构造方法
        Constructor c1 = vipClass.getDeclaredConstructor(int.class, String.class, String.class, boolean.class);
        Object obj2 = c1.newInstance(321, "lsi", "1999-10-11", true);
        System.out.println(obj2);
        
        // 获取无参数构造方法
        Constructor c2 = vipClass.getDeclaredConstructor();
        Object obj3 = c2.newInstance();
        System.out.println(obj3);
    }
}

十二、获取父类和实现的接口

Class类方法:

  • public native Class<? super T> getSuperclass():返回调用类的父类
  • public Class<?>[] getInterfaces():返回调用类实现的接口集合

示例代码:

class ReflectTest13 {
    public static void main(String[] args) throws Exception {
        Class vipClass = Class.forName("java.lang.String");
        Class superclass = vipClass.getSuperclass();
        Class[] interfaces = vipClass.getInterfaces();
        System.out.println(superclass.getName());
        for (Class i : interfaces) {
            System.out.println(i.getName());
        }
    }
}

十三、关键点总结

  1. Class.forName(classname):获取classname类中的所有属性包括类名
  2. Class.newInstance():实例化对象,并触发该类的构造方法
  3. Class.getMethod(method name,arg):获取一个对象中的public方法
  4. Method.invoke():执行方法
    • 普通方法:第一个参数为该方法所在的对象
    • 静态方法:第一个参数是null或者该方法所在的类
    • 第二个参数为要执行方法的参数
  5. obj.getClass():通过对象实例获取它的类
  6. Y1.class:直接通过类名获取Class对象

十四、形参和实参

  • 形参:定义函数时使用的参数,用于接收调用该函数时传入的参数
  • 实参:调用函数时,函数名后面括号中的参数

十五、变量赋值方式

  1. 基本数据类型:赋值的是变量所保存的数据值
  2. 引用数据类型:赋值的是变量所保存的数据的地址值

十六、值传递机制

  1. 基本数据类型参数:实参赋给形参的是实参真实存储的数据值
  2. 引用数据类型参数:实参赋给形参的是实参存储数据的地址值

示例说明:

public class ValueTransferTest1 {
    public static void main(String[] args) {
        int m = 10;
        int n = 20;
        swap(m, n);  // 交换失败,因为是值传递
        System.out.println("m = " + m + ", n = " + n);
    }
    
    public static void swap(int m, int n) {
        int temp = m;
        m = n;
        n = temp;
    }
}

public class ValueTransferTest2 {
    public static void main(String[] args) {
        Data data = new Data();
        data.m = 10;
        data.n = 20;
        swap(data);  // 交换成功,因为是引用传递
        System.out.println("m = " + data.m + ", n = " + data.n);
    }
    
    public static void swap(Data data) {
        int temp = data.m;
        data.m = data.n;
        data.n = temp;
    }
}

class Data {
    int m;
    int n;
}

十七、反射应用场景

  1. 动态代理:AOP实现
  2. 框架设计:Spring等框架的核心
  3. 注解处理:运行时注解处理器
  4. 工具类:通用工具方法
  5. 测试工具:Mock测试等

十八、反射性能考虑

反射操作比直接调用慢,因为:

  1. 需要动态解析类型
  2. 需要安全检查
  3. 编译器无法优化

优化建议

  1. 缓存Class对象
  2. 缓存Method/Field/Constructor对象
  3. 减少安全检查(setAccessible(true))
Java反射机制详解 一、反射概念 Java反射是指在程序运行期间对于类的属性、方法、构造方法等进行动态访问和操作的机制。通过Java反射API,程序能够在运行期获取类的信息,操作类的属性、方法、构造方法,创建类的对象等。 核心特点 :不适用new创建对象而访问类中方法的过程即可成为反射。 二、反射相关包 Java反射的相关类位于 java.lang.reflect.* 包中。 三、反射的作用 获取任意类的名称、package信息、所有属性、方法、注解、类型、类加载器等 获取任意对象的属性,并且能改变对象的属性 调用任意对象的方法 判断任意一个对象所属的类 实例化任意一个类的对象 实现动态装配,降低代码的耦合度,动态代理等 四、核心反射类 java.lang.Class :代表整个字节码,代表一个类型,代表整个类 java.lang.reflect.Method :代表字节码中的方法字节码,代表类中的方法 java.lang.reflect.Constructor :代表字节码中的构造方法字节码,代表类中的构造方法 java.lang.reflect.Field :代表字节码中的属性字节码,代表类中的成员变量(静态变量+实例变量) 注意 :必须先获取Class才能获取Method、Constructor、Field。 五、获取Class实例的三种方法 Class.forName("完整类名带包名") 对象.getClass() 类名.class 六、Class类常用方法 | 方法 | 描述 | |------|------| | getFields() | 获得类的public类型的属性 | | getDeclaredFields() | 获得类的所有属性 | | getField(String name) | 获得类的指定属性 | | getMethods() | 获得类的public类型的方法 | | getMethod(String name, Class[] args) | 获得类的指定方法 | | getConstrutors() | 获得类的public类型的构造方法 | | getConstrutor(Class[] args) | 获得类的特定构造方法 | | newInstance() | 通过类的无参构造方法创建对象 | | getName() | 获得类的完整名字 | | getPackage() | 获取此类所属的包 | | getSuperclass() | 获得此类的父类对应的Class对象 | 七、通过反射实例化对象 基本方法: 注意 :没有公共的无参构造函数,newInstance()方法就会抛出InstantiationException异常 使用特定构造函数: 八、Class.forName导致类加载 如果只是希望一个类的静态代码块执行,其它代码一律不执行,可以使用: 这个方法的执行会导致类加载,类加载时,静态代码块执行。 九、反射Field(反射/反编译一个类的属性) Class类相关方法: public T newInstance() :创建对象 public String getName() :返回完整类名带包名 public String getSimpleName() :返回类名 public Field[] getFields() :返回类中public修饰的属性 public Field[] getDeclaredFields() :返回类中所有的属性 public Field getDeclaredField(String name) :根据属性名name获取指定的属性 public native int getModifiers() :获取属性的修饰符列表,返回的修饰符是一个数字 public Method[] getDeclaredMethods() :返回类中所有的实例方法 public Method getDeclaredMethod(String name, Class<?>... parameterTypes) :根据方法名name和方法形参获取指定方法 public Constructor<?>[] getDeclaredConstructors() :返回类中所有的构造方法 public Constructor getDeclaredConstructor(Class<?>... parameterTypes) :根据方法形参获取指定的构造方法 public native Class<? super T> getSuperclass() :返回调用类的父类 public Class<?>[] getInterfaces() :返回调用类实现的接口集合 Field类方法: public String getName() :返回属性名 public int getModifiers() :获取属性的修饰符列表 public Class<?> getType() :以Class类型,返回属性类型 public void set(Object obj, Object value) :设置属性值 public Object get(Object obj) :读取属性值 给属性赋值和读取: 直接赋值: 通过反射赋值: 示例代码: 十、反射Method(反射/反编译一个类的方法) Method类方法: public String getName() :返回方法名 public int getModifiers() :获取方法的修饰符列表 public Class<?> getReturnType() :以Class类型,返回方法类型 public Class<?>[] getParameterTypes() :返回方法的修饰符列表 public Object invoke(Object obj, Object... args) :调用方法 调用方法: 示例代码: 十一、反射Constructor(反射/反编译一个类的构造方法) Constructor类方法: public String getName() :返回构造方法名 public int getModifiers() :获取构造方法的修饰符列表 public Class<?>[] getParameterTypes() :返回构造方法的修饰符列表 public T newInstance(Object ... initargs) :创建对象 示例代码: 十二、获取父类和实现的接口 Class类方法: public native Class<? super T> getSuperclass() :返回调用类的父类 public Class<?>[] getInterfaces() :返回调用类实现的接口集合 示例代码: 十三、关键点总结 Class.forName(classname) :获取classname类中的所有属性包括类名 Class.newInstance() :实例化对象,并触发该类的构造方法 Class.getMethod(method name,arg) :获取一个对象中的public方法 Method.invoke() :执行方法 普通方法:第一个参数为该方法所在的对象 静态方法:第一个参数是null或者该方法所在的类 第二个参数为要执行方法的参数 obj.getClass() :通过对象实例获取它的类 Y1.class :直接通过类名获取Class对象 十四、形参和实参 形参 :定义函数时使用的参数,用于接收调用该函数时传入的参数 实参 :调用函数时,函数名后面括号中的参数 十五、变量赋值方式 基本数据类型 :赋值的是变量所保存的数据值 引用数据类型 :赋值的是变量所保存的数据的地址值 十六、值传递机制 基本数据类型参数 :实参赋给形参的是实参真实存储的数据值 引用数据类型参数 :实参赋给形参的是实参存储数据的地址值 示例说明: 十七、反射应用场景 动态代理 :AOP实现 框架设计 :Spring等框架的核心 注解处理 :运行时注解处理器 工具类 :通用工具方法 测试工具 :Mock测试等 十八、反射性能考虑 反射操作比直接调用慢,因为: 需要动态解析类型 需要安全检查 编译器无法优化 优化建议 : 缓存Class对象 缓存Method/Field/Constructor对象 减少安全检查(setAccessible(true))