跳到主要内容

Java 反射

提示
  1. 反射的核心概念:Java 反射允许在运行时检查和操作类、接口、构造器、方法和字段。
  2. Class 类的应用:通过创建 Class 类的对象,可以获得类的运行时信息,并执行反射操作。
  3. 反射方法、字段和构造器:使用 java.lang.reflect 包中的 MethodFieldConstructor 类进行详细的类成员操作和信息获取。

在 Java 中,反射允许我们在运行时检查和操作类、接口、构造器、方法和字段。

Java 中有一个名为 Class 的类,它在运行时保存了有关对象和类的所有信息。Class 的对象可以用来执行反射。

Java 类的反射

为了反射一个 Java 类,我们首先需要创建一个 Class 的对象。

使用这个对象,我们可以调用各种方法来获取类中存在的方法、字段和构造器的信息。

有三种方法可以创建 Class 的对象:

1. 使用 forName() 方法

class Dog {...}

// 创建 Class 的对象
// 以反射 Dog 类
Class a = Class.forName("Dog");

这里,forName() 方法以要被反射的类的名称作为其参数。

2. 使用 getClass() 方法

// 创建 Dog 类的对象
Dog d1 = new Dog();

// 创建 Class 的对象
// 以反射 Dog
Class b = d1.getClass();

这里,我们使用 Dog 类的对象来创建 Class 的对象。

3. 使用 .class 扩展

// 创建 Class 的对象
// 以反射 Dog 类
Class c = Dog.class;

现在我们知道了如何创建 Class 的对象。我们可以使用这个对象来获取相应类在运行时的信息。

示例:Java 类的反射

import java.lang.Class;
import java.lang.reflect.*;

class Animal {
}

// 将此类放在不同的 Dog.java 文件中
public class Dog extends Animal {
public void display() {
System.out.println("我是一只狗。");
}
}

// 将此放在 Main.java 文件中
class Main {
public static void main(String[] args) {
try {
// 创建一个 Dog 的对象
Dog d1 = new Dog();

// 使用 getClass() 创建 Class 的对象
Class obj = d1.getClass();

// 获取类的名称
String name = obj.getName();
System.out.println("名称: " + name);

// 获取类的访问修饰符
int modifier = obj.getModifiers();

// 将访问修饰符转换为字符串
String mod = Modifier.toString(modifier);
System.out.println("修饰符: " + mod);

// 获取 Dog 的超类
Class superClass = obj.getSuperclass();
System.out.println("超类: " + superClass.getName());
}

catch (Exception e) {
e.printStackTrace();
}
}
}

输出

名称: Dog
修饰符: public
超类: Animal

在上面的示例中,我们创建了一个超类:Animal 和一个子类:Dog。这里,我们试图检查 Dog 类。

注意这个语句,

Class obj = d1.getClass();

在这里,我们使用 getClass() 方法创建了 Class 的对象 obj。使用这个对象,我们调用了 Class 的不同方法。

  • obj.getName() - 返回类的名称
  • obj.getModifiers() - 返回类的访问修饰符
  • obj.getSuperclass() - 返回类的超类

要了解更多关于 Class 的信息,请访问 Java Class(官方 Java 文档)

注意:我们使用了 Modifier 类将整型的访问修饰符转换为字符串。

反射字段、方法和构造器

java.lang.reflect 包提供了可以用于操作类成员的类。例如,

  • Method 类 - 提供关于类中方法的信息
  • Field 类 - 提供关于类中字段的信息
  • Constructor 类 - 提供关于类中构造器的信息

1. Java 方法的反射

Method 类提供了各种方法,可以用来获取类中存在的方法的信息。例如,

import java.lang.Class;
import java.lang.reflect.*;

class Dog {

// 类的方法
public void display() {
System.out.println("我是一只狗。");
}

private void makeSound() {
System.out.println("汪汪");
}
}

class Main {
public static void main(String[] args) {
try {

// 创建 Dog 的对象
Dog d1 = new Dog();

// 使用 getClass() 创建 Class 的对象
Class obj = d1.getClass();

// 使用 Class 的对象来
// 获取 Dog 所有声明的方法
Method[] methods = obj.getDeclaredMethods();

// 创建 Method 类的对象
for (Method m : methods) {

// 获取方法的名称
System.out.println("方法名称: " + m.getName());

// 获取方法的访问修饰符
int modifier = m.getModifiers();
System.out.println("修饰符: " + Modifier.toString(modifier));

// 获取方法的返回类型
System.out.println("返回类型: " + m.getReturnType());
System.out.println(" ");
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}

输出

方法名称: display
修饰符: public
返回类型: void

方法名称: makeSound
修饰符: private
返回类型: void

在上面的示例中,我们试图获取 Dog 类中存在的方法的信息。如前所述,我们首先使用 getClass() 方法创建了 Class 的对象 obj

注意表达式,

Method[] methods = obj.getDeclaredMethod();

这里,getDeclaredMethod() 返回类内所有存在的方法。

同时,我们创建了 Method 类的对象 m。这里,

  • m.getName() - 返回方法的名称
  • m.getModifiers() - 以整数形式返回方法的访问修饰符
  • m.getReturnType() - 返回方法的返回类型

Method 类还提供了其他各种方法,可用于在运行时检查方法。要了解更多,请访问 Java Method 类(官方 Java 文档)

2. Java 字段的反射

与方法类似,我们也可以使用 Field 类的方法来检查和修改类中不同字段。例如,

import java.lang.Class;
import java.lang.reflect.*;

class Dog {
public String type;
}

class Main {
public static void main(String[] args) {
try {
// 创建 Dog 的对象
Dog d1 = new Dog();

// 使用 getClass() 创建 Class 的对象
Class obj = d1.getClass();

// 访问并设置 type 字段
Field field1 = obj.getField("type");
field1.set(d1, "拉布拉多");

// 获取字段 type 的值
String typeValue = (String) field1.get(d1);
System.out.println("值: " + typeValue);

// 获取字段 type 的访问修饰符
int mod = field1.getModifiers();

//

将修饰符转换为字符串形式
String modifier1 = Modifier.toString(mod);
System.out.println("修饰符: " + modifier1);
System.out.println(" ");
}

catch (Exception e) {
e.printStackTrace();
}
}
}

输出

: 拉布拉多
修饰符: public

在上面的示例中,我们创建了一个名为 Dog 的类。它包含一个名为 type 的公共字段。注意这个语句,

Field field1 = obj.getField("type");

这里,我们正在访问 Dog 类的公共字段,并将其赋给 Field 类的对象 field1

然后我们使用了 Field 类的不同方法:

  • field1.set() - 设置字段的值
  • field1.get() - 返回字段的值
  • field1.getModifiers() - 以整数形式返回字段的修饰符值

类似地,我们也可以访问和修改私有字段。然而,私有字段的反射与公共字段有些不同。例如,

import java.lang.Class;
import java.lang.reflect.*;

class Dog {
private String color;
}

class Main {
public static void main(String[] args) {
try {
// 创建 Dog 的对象
Dog d1 = new Dog();

// 使用 getClass() 创建 Class 的对象
Class obj = d1.getClass();

// 访问私有字段 color
Field field1 = obj.getDeclaredField("color");

// 允许修改私有字段
field1.setAccessible(true);

// 设置 color 的值
field1.set(d1, "棕色");

// 获取字段 color 的值
String colorValue = (String) field1.get(d1);
System.out.println("值: " + colorValue);

// 获取 color 的访问修饰符
int mod2 = field1.getModifiers();

// 将访问修饰符转换为字符串
String modifier2 = Modifier.toString(mod2);
System.out.println("修饰符: " + modifier2);
}

catch (Exception e) {
e.printStackTrace();
}
}
}

输出

: 棕色
修饰符: private

在上面的示例中,我们创建了一个名为 Dog 的类。这个类包含一个名为 color 的私有字段。注意以下声明。

Field field1 = obj.getDeclaredField("color");

field1.setAccessible(true);

这里,我们正在访问 color 并将其分配给 Field 类的对象 field1。然后我们使用 field1 修改了 color 的可访问性,并允许我们对其进行更改。

接着我们使用 field1 对私有字段 color 进行了各种操作。

要了解有关 Field 的不同方法的更多信息,请访问 Java Field 类(官方 Java 文档)

3. Java 构造器的反射

我们还可以使用 Constructor 类提供的各种方法来检查类的不同构造器。例如,

import java.lang.Class;
import java.lang.reflect.*;

class Dog {

// 无参数的公共构造器
public Dog() {

}

// 带单个参数的私有构造器
private Dog(int age) {

}

}

class Main {
public static void main(String[] args) {
try {
// 创建 Dog 的对象
Dog d1 = new Dog();

// 使用 getClass() 创建 Class 的对象
Class obj = d1.getClass();

// 获取 Dog 的所有构造器
Constructor[] constructors = obj.getDeclaredConstructors();

for (Constructor c : constructors) {

// 获取构造器的名称
System.out.println("构造器名称: " + c.getName());

// 获取构造器的访问修饰符
// 并转换为字符串形式
int modifier = c.getModifiers();
String mod = Modifier.toString(modifier);
System.out.println("修饰符: " + mod);

// 获取构造器中参数的数量
System.out.println("参数数量: " + c.getParameterCount());
System.out.println("");
}
}

catch (Exception e) {
e.printStackTrace();
}
}
}

输出

构造器名称: Dog
修饰符: public
参数数量: 0

构造器名称: Dog
修饰符: private
参数数量: 1

在上述示例中,我们创建了一个名为 Dog 的类。这个类包括两个构造器。

我们使用反射来查找类的构造器信息。注意以下声明,

Constructor[] constructors = obj.getDeclaredConstructor();

这里,我们正在访问 Dog 中所有的构造器,并将它们分配给 Constructor 类型的数组 constructors

然后我们使用对象 c 获取有关构造器的不同信息。

  • c.getName() - 返回构造器的名称
  • c.getModifiers() - 以整数形式返回构造器的访问修饰符
  • c.getParameterCount() - 返回每个构造器中存在的参数数量

要了解更多关于 Constructor 类的方法,请访问 Constructor 类