> ## Content Index
> Fetch the complete content index at: https://iiong.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# 十分钟搞清 Java 反射
- URL: https://iiong.com/java-reflection-learning-notes/
- Published: 2024-07-03T14:30:36.000Z
- Updated: 2026-06-22T15:24:40.000Z
- Description: 反射是 Java 的一种机制，可以在运行时获取类的信息作用，通过反射可以在程序运行时动态创建对象，还能获取到类的所有信息，比如它的属性、构造器、方法、注解等。
- Author: 淮城一只猫
- Tags: 编程技术

### 前言

因为后续在开发 `Xposed` 模块的时候，发现需要 `Java` 反射的概念，这几年没怎么接触反射的概念，就花点时间回忆下反射基础内容。

> 反射是 Java 的一种机制，可以在运行时获取类的信息作用，通过反射可以在程序运行时动态创建对象，还能获取到类的所有信息，比如它的属性、构造器、方法、注解等。

### 正射和反射

如果有反射那肯定有所谓的“正射”，正射就是在平常开发中知道的类，并且去创建实例化它：

```java
public class Apple {

    private int price;
    public int publicPrice;
    private int privatePrice;

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }
}

```

比如上面的 `Apple` 类直接实例化：

```java
public class Main {
    public static void main(String[] args) throws Exception {
        Apple apple = new Apple();
        apple.setPrice(4);
        System.out.println("正射：" + apple.getPrice());
    }
}

```

这个过程就是所谓的正射，那反射指的是在运行情况下通过字符串值知道要运行的类，然后获取类的构造且调用对应的方法：

```java
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws Exception {
        // 获取类的 Class 对象实例，根据包名路径走，例如（com.iiong.Apple）
        Class<?> clazz = Class.forName("Apple");
        // 根据 Class 对象实例获取 Constructor 对象
        Constructor<?> appleConstructor = clazz.getConstructor();
        // 使用 Constructor 对象的 newInstance 方法获取反射类对象
        Object appleObj = appleConstructor.newInstance();
        // 获取方法的 Method 对象
        Method setPriceMethod = clazz.getMethod("setPrice", int.class);
        // 利用 invoke 方法调用方法
        setPriceMethod.invoke(appleObj, 5);
        // 获取方法的 Method 对象
        Method getPriceMethod = clazz.getMethod("getPrice");
        // 输出利用 invoke 方法调用方法的数据
        System.out.println("反射：" + getPriceMethod.invoke(appleObj));
    }
}

```

最后输出的结果和正射代码是一样的，到此为止对反射掌握基本使用了，反射的应用场景：

- Spring 实例化对象：当程序启动时，Spring 会读取配置文件applicationContext.xml并解析出里面所有的标签实例化到IOC容器中。
- 反射 + 工厂模式：通过反射消除工厂中的多个分支，如果需要生产新的类，无需关注工厂类，工厂类可以应对各种新增的类，反射可以使得程序更加健壮。
- JDBC连接数据库：使用JDBC连接数据库时，指定连接数据库的驱动类时用到反射加载驱动类。
- ...

### 扩展

获取 `Class` 对象有三种方式，分别如下：

- 根据类名：`Apple.class`

```Java
Class clazz = Apple.class;

```

- 根据对象：`new Apple().getClass()`

```Java
Apple apple = new Apple();
Class clazz = apple.getClass();

```

- 根据全限定类名：`Class.forName("com.iiong.Apple")`，也是本案例使用的方法

通过反射创建类对象主要通过俩个方式：

- 通过 `Class` 对象的 `newInstance()` 方法

```java
Class clazz = Apple.class;
Apple apple = (Apple)clazz.getDeclaredConstructor().newInstance();

```

- 通过 `Constructor` 对象的 `newInstance()` 方法，也是本案例使用的方法

```java
Class clazz = Apple.class;
Constructor<?> appleConstructor = clazz.getConstructor();
Apple apple = appleConstructor.newInstance();

```

同样我们可以通过 `Class` 对象的 `getFields()` 方法获取 `Class` 类的属性，但无法获取私有属性。

```java
Class clazz = Apple.class;
Field[] fields = clazz.getFields();
for (Field field : fields) {
    System.out.println("Apple 类属性：" + field.getName());
}

```

打印的时候发现 `private` 声明的属性不会输出，所以这时候需要使用 `getDeclaredFields` 方法：

```java
Field[] privateFields = clazz.getDeclaredFields();
for (Field field : privateFields) {
    System.out.println("Apple 类属性：" + field.getName());
}

```

与获取类属性一样，当我们去获取类方法、类构造器时，如果要获取私有方法或私有构造器，则必须使用有 `declared` 关键字的方法。

| **方法名**            | **说明**                                                                                                          |
| ------------------ | --------------------------------------------------------------------------------------------------------------- |
| forName()          | \- 获取 Class 对象的一个引用，但引用的类还没有加载(该类的第一个对象没有生成)就加载了这个类\- 为了产生 Class 引用，forName() 立即就进行了初始化                         |
| Object-getClass()  | 获取Class对象的一个引用，返回表示该对象的实际类型的Class引用                                                                             |
| getName()          | 取全限定的类名(包括包名)，即类的完整名字                                                                                           |
| getSimpleName()    | 获取类名(不包括包名)                                                                                                     |
| getCanonicalName() | 获取全限定的类名(包括包名)                                                                                                  |
| isInterface()      | 判断 Class 对象是否是表示一个接口                                                                                            |
| getInterfaces()    | 返回 Class 对象数组，表示Class对象所引用的类所实现的所有接口                                                                            |
| getSupercalss()    | 返回 Class 对象，表示 Class 对象所引用的类所继承的直接基类，应用该方法可在运行时发现一个对象完整的继承结构                                                    |
| newInstance()      | 返回一个Oject对象，是实现“虚拟构造器”的一种途径。使用该方法创建的类，必须带有无参的构造器                                                                |
| getFields()        | 获得某个类的所有的公共 public 的字段，包括继承自父类的所有公共字段。 类似的还有 getMethods 和 getConstructors                                       |
| getDeclaredFields  | 获得某个类的自己声明的字段，即包括 public、private 和 proteced ，默认但是不包括父类声明的任何字段。类似的还有 getDeclaredMethods 和getDeclaredConstructors |