Java 反射
在本教程中,我们将学习 Java 反射,反射允许我们在运行时操作类、接口、构造函数、方法和属性字段。
在本教程中,我们将学习 Java 反射,反射允许我们在运行时操作类、接口、构造函数、方法和属性字段。
Java 中有一个名为的 Class
类,它在运行时保存有关对象和类的所有信息。 Class
类的对象可以用来执行反射。
Java 类的反射
为了反射一个 Java 类,我们首先需要创建或者获取当前类 Class
对象。
使用 Class
类,我们可以调用各种方法来获取有关类中存在的方法、字段和构造函数的信息。
有三种获取 Class 对象的方法:
-
使用
Class.forName()
方法public class Dog {...} Class a = Class.forName("Dog");
在这里,
forName()
方法将要反射的类的名称作为其参数。如果类在某个包内,则使用类的全名作为参数,比如:net.gobeta.Dog
-
使用
obj.getClass()
方法Dog d1 = new Dog(); Class b = d1.getClass();
在这里,我们在
d1
对象上调用getClass()
方法返回Class
对象。 -
使用类的静态
class
属性Class c = Dog.class;
现在我们知道了如何获取 Class
对象, 我们可以使用此对象在运行时获取有关类的信息,比如方法、属性、注解等。
示例:Java 类反射
import java.lang.Class;
import java.lang.reflect.*;
class Animal {}
final class Dog extends Animal {
public void display() {
System.out.println("I am a dog.");
}
}
public class Main {
public static void main(String[] args) {
try {
// 创建对象
Dog d1 = new Dog();
// 获取 Class 对象
Class clazz = d1.getClass();
// 获取类型
String name = clazz.getName();
System.out.println("Name: " + name);
// 获取类的修饰符
int modifier = clazz.getModifiers();
// 将修饰符转为字符串
String mod = Modifier.toString(modifier);
System.out.println("Modifier: " + mod);
// 获取父类
Class superClass = clazz.getSuperclass();
System.out.println("Superclass: " + superClass.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出
Name: Dog
Modifier: final
Superclass: Animal
在上面的例子中,我们创建了一个父类 Animal
和一个子类 Dog
,我们要获取 Dog
类的信息。注意语句:
public class clazz = d1.getClass();
通过上面的语句我们获取到 Dog
类关联的类对象。我们调用类对象的不同方法获取类的信息:
clazz.getName()
- 返回类的名称clazz.getModifiers()
- 返回类的访问修饰符clazz.getSuperclass()
- 返回类的超类
! 注意:我们使用 Modifier
类将访问修饰符从整数转换为字符串。
反射字段、方法和构造函数
java.lang.reflect
包里有很多用于和操作类成员的类。例如:
Method
- 封装了类的一个方法的信息Field
- 封装了类的一个属性字段的信息Constructor
- 封装了类中构造函数的信息
Java 方法的反射
Method
类提供了可用于获取存在于类中的方法信息的各种方法。例如,
import java.lang.Class;
import java.lang.reflect.*;
class Dog {
// methods of the class
public void display() {
System.out.println("I am a dog.");
}
private void makeSound() {
System.out.println("Bark Bark");
}
}
public class Main {
public static void main(String[] args) {
try {
Dog d1 = new Dog();
// 获取类对象
Class clazz = d1.getClass();
// 获取类中所有方法的数组
Method[] methods = clazz.getDeclaredMethods();
// 遍历所有方法对象
for (Method m : methods) {
// 方法名
System.out.println("Method Name: " + m.getName());
// 方法修饰符
int modifier = m.getModifiers();
System.out.println("Modifier: " + Modifier.toString(modifier));
// 方法返回值
System.out.println("Return Type: " + m.getReturnType());
System.out.println();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出
Method Name: display
Modifier: public
Return Type: void
Method Name: makeSound
Modifier: private
Return Type: void
在上面的例子中,我们通过以下语句获取 Dog
类中的所有的方法的数组:
Method[] methods = clazz.getDeclaredMethod();
在遍历方法数组的时候,我们打印每个 Method
对象的信息:
getName()
- 返回方法的名称getModifiers()
- 以整数形式返回方法的访问修饰符getReturnType()
- 返回方法的返回类型
Method
类还提供了可被用于检查在运行时的方法的各种其它方法。
Java 字段的反射
Field
类提供了可用于获取存类中的属性信息的各种方法。例如,
import java.lang.Class;
import java.lang.reflect.*;
class Dog {
public String type;
}
public class Main {
public static void main(String[] args) {
try {
Dog d1 = new Dog();
// 获取类对象
Class clazz = d1.getClass();
// 获取 type 属性的对象
Field field1 = clazz.getField("type");
// 为对象设置 type 属性的值
field1.set(d1, "labrador");
// 获取对象 type 属性的值
String typeValue = (String) field1.get(d1);
System.out.println("Value: " + typeValue);
// 获取属性的访问修饰符
int mod = field1.getModifiers();
String modifier1 = Modifier.toString(mod);
System.out.println("Modifier: " + modifier1);
System.out.println(" ");
} catch (Exception e) {
e.printStackTrace();
}
}
}
import java.lang.Class;
import java.lang.reflect.*;
class Dog {
public String type;
}
public class Main {
public static void main(String[] args) {
try {
Dog d1 = new Dog();
// 获取类对象
Class clazz = d1.getClass();
// 获取 type 属性的对象
Field field1 = clazz.getField("type");
// 为对象设置 type 属性的值
field1.set(d1, "labrador");
// 获取对象 type 属性的值
String typeValue = (String) field1.get(d1);
System.out.println("Value: " + typeValue);
// 获取属性的访问修饰符
int mod = field1.getModifiers();
String modifier1 = Modifier.toString(mod);
System.out.println("Modifier: " + modifier1);
System.out.println(" ");
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出
Value: labrador
Modifier: public
在上面的例子中,我们创建了一个 Dog
类,它有一个公共的字符串字段 type
。 注意下面的语句:
Field field1 = clazz.getField("type");
在这里,我们从 Dog
类对应的 Class
对象中返回 type
字段对应 Field
对象。
然后我们使用了 Field
类的各种方法:
field1.set()
- 设置字段的值field1.get()
- 返回字段的值field1.getModifiers()
- 以整数形式返回字段的值
同样,我们也可以访问和修改私有字段。但是,私有字段的反射与公共字段略有不同。下面的例子展示了如何使用反射操作私有字段:
import java.lang.Class;
import java.lang.reflect.*;
class Dog {
private String color;
}
public class Main {
public static void main(String[] args) {
try {
Dog d1 = new Dog();
// 获取对应的类对象
Class clazz = d1.getClass();
// 访问私有属性
Field field1 = clazz.getDeclaredField("color");
// 修改私有属性的为可访问
field1.setAccessible(true);
// 设置属性值
field1.set(d1, "brown");
// 返回属性值
String colorValue = (String) field1.get(d1);
System.out.println("Value: " + colorValue);
// 获取属性的修饰符
int mod2 = field1.getModifiers();
String modifier2 = Modifier.toString(mod2);
System.out.println("Modifier: " + modifier2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出
Value: brown
Modifier: private
在上面的例子中,我们创建了一个 Dog
类,它有一个私有字符串字段 color
,注意下面的语句:
Field field1 = clazz.getDeclaredField("color");
field1.setAccessible(true);
我们先通过 clazz.getDeclaredField("color")
获取属性对应的 Field
对象,然后使用 field1.setAccessible(true)
方法设置属性为可修改。然后我们对私有字段执行各种操作。
Java 构造函数的反射
我们还可以使用 Constructor
类提供的各种方法操作类的构造函数 Constructor
。例如:
import java.lang.Class;
import java.lang.reflect.*;
public class Dog {
public Dog() {}
private Dog(int age) {}
}
public class Main {
public static void main(String[] args) {
try {
Dog d1 = new Dog();
Class clazz = d1.getClass();
Constructor[] constructors = clazz.getDeclaredConstructors();
for (Constructor c : constructors) {
System.out.println("Constructor Name: " + c.getName());
int modifier = c.getModifiers();
String mod = Modifier.toString(modifier);
System.out.println("Modifier: " + mod);
System.out.println("Parameters: " + c.getParameterCount());
System.out.println("");
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
输出
Constructor Name: Dog
Modifier: public
Parameters: 0
Constructor Name: Dog
Modifier: private
Parameters: 1
在上面的例子中,我们创建了一个 Dog
类,该类包括两个构造函数。我们使用反射来查找有 Dog
类的构造函数的信息。注意以下语句:
Constructor[] constructors = clazz.getDeclaredConstructor();
在这里,我们获取中 Dog
类所有的构造函数并将它们分配给一个 Constructor
类型数组。
遍历的时候,我们获取每个 Constructor
对象的信息。
c.getName()
- 返回构造函数的名称c.getModifiers()
- 以整数形式返回构造函数的访问修饰符c.getParameterCount()
- 返回每个构造函数中存在的参数数量