java面向对象之反射基础

109 阅读3分钟

反射是 Java 提供的一种强大机制,允许程序在运行时获取类的信息和操作对象。它的原理主要基于 Java 的类加载机制和 java.lang.reflect 包中的类。以下是反射的核心原理及其工作方式:

image.png

1. 类加载机制

  • 类加载器:Java 使用类加载器来加载类文件。类加载器将类的字节码加载到 JVM 中,并为每个类创建一个 Class 对象。
  • Class 对象:每个类在 Java 中都有一个对应的 Class 对象,包含了类的结构信息(如字段、方法、构造函数等)。

2. java.lang.reflect

  • 反射的核心 API 位于 java.lang.reflect 包中,主要包括以下几个类:

    • Class:表示类的结构,可以获取类的信息。
    • Field:表示类的字段,可以获取和修改字段的值。
    • Method:表示类的方法,可以调用方法。
    • Constructor:表示类的构造函数,可以创建对象。

3. 反射的基本操作

  • 获取 Class 对象

    • 通过类的名字、实例对象或类字面量获取 Class 对象。
    Class<?> clazz = MyClass.class; // 通过类字面量
    Class<?> clazz = obj.getClass(); // 通过实例对象
    Class<?> clazz = Class.forName("com.example.MyClass"); // 通过类名
    
  • 获取信息

    • 使用 Class 对象获取构造函数、方法和字段的信息。
    Method[] methods = clazz.getDeclaredMethods();
    Field[] fields = clazz.getDeclaredFields();
    
  • 创建实例

    • 通过 Constructor 对象创建类的实例。
    Constructor<?> constructor = clazz.getConstructor();
    Object instance = constructor.newInstance();
    
  • 调用方法

    • 使用 Method 对象调用类的方法。
    Method method = clazz.getMethod("myMethod", String.class);
    method.invoke(instance, "Hello");
    
  • 访问字段

    • 使用 Field 对象获取或修改字段的值。

image.png

```java
Field field = clazz.getDeclaredField("myField");
field.setAccessible(true); // 允许访问私有字段
Object value = field.get(instance);
```

4. 性能和安全性

  • 性能:反射操作相对较慢,因为它涉及到动态查找和方法调用,因此应谨慎使用,尤其是在性能敏感的场合。
  • 安全性:反射可以访问私有成员,因此在使用时需要注意安全性和数据保护。

总结

反射是 Java 中一种强大的灵活性机制,允许程序在运行时动态地获取类的信息和操作对象。通过反射,开发者能够实现高度可配置和可扩展的应用程序,但也需要注意其带来的性能和安全性问题。

image.png

最终练习

package reflect;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * @Author xushupeng
 * @Date 2024-12-13 16:09
 * 注意看配置文件
 */
public class 反射练习结合配置文件动态创建 {

    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.读取配置文件
        Properties properties = new Properties();
        FileInputStream fis=new FileInputStream("src/reflect/prop.properties");
        properties.load(fis);
        fis.close();
        System.out.println(properties);
        //2.获取配置文件中的全类名
        String classname=properties.getProperty("classname");
        System.out.println(classname);
        //获取配置文件的方法名
        String methodName=properties.getProperty("method");
        System.out.println(methodName);
        //根据全类名 获取字节码文件对象
        Class clazz=Class.forName(classname);
        //获取构造方法 getDeclaredConstructor() 方法用于获取该类的默认构造函数(即无参数的构造函数)  如果方法中含有参数 那么就可以指定构造函数
        Constructor con = clazz.getDeclaredConstructor(String.class, int.class);


        Object o=con.newInstance("xsp",22);

        System.out.println(o);
        Student student=(Student)o;//向下转型
        student.info();
        
        //获取成员方法并运行
        Method method = clazz.getDeclaredMethod(methodName);
        method.setAccessible(true);
        method.invoke(o);
        
    }

}

配置文件如下

image.png