在本教程中,我们将学习反射,这是Java编程中的一个特性,它允许我们检查和修改类、方法等。
在Java中,反射允许我们在运行时检查和操作类、接口、构造函数、方法和字段。
在学习Java反射之前,我们需要了解一个名为Class的Java类。
Java中有一个名为Class的类,该类在运行时保留有关对象和类的所有信息。
Class对象描述了特定类的属性。该对象用于执行反射。
我们可以创建Class的对象,通过:
使用forName()方法
forName()接受字符串参数(类的名称)并返回Class对象。返回的对象引用字符串指定的类。例如,
Class Dog { } Class c1 = Class.forName("Dog");
使用getClass()方法
getClass()方法使用特定类的对象来创建新的对象Class。例如,
Dog d1 = new Dog() Class c1 = d1.getClass();
使用.class
我们还可以使用 .class 扩展名创建Class对象。例如,
Class c1 = Dog.class;
创建Class对象后,我们可以使用这些对象执行反射。
我们可以使用Class的getInterfaces()方法来收集类实现的接口的信息。此方法返回一个接口数组。
import java.lang.Class; import java.lang.reflect.*; interface Animal { public void display(); interface Mammal { public void makeSound(); class Dog implements Animal, Mammal { public void display() { System.out.println("I am a dog."); public void makeSound() { System.out.println("Bark bark"); class ReflectionDemo { public static void main(String[] args) { try { //创建一个Dog类的对象 Dog d1 = new Dog(); //使用getClass()创建Class对象 Class obj = d1.getClass(); //查找由Dog实现的接口 Class[] objInterface = obj.getInterfaces(); for(Class c : objInterface) { //打印接口名称 System.out.println("Interface Name: " + c.getName()); catch(Exception e) { e.printStackTrace(); }
输出结果
Interface Name: Animal Interface Name: Mammal
类Class的方法getSuperclass()可用于获取有关特定类的超类的信息。
而且,Class提供了一种getModifier()方法,该方法以整数形式返回class的修饰符。
import java.lang.Class; import java.lang.reflect.*; interface Animal { public void display(); public class Dog implements Animal { public void display() { System.out.println("I am a dog."); class ReflectionDemo { public static void main(String[] args) { try { //创建一个Dog类的对象 Dog d1 = new Dog(); //使用getClass()创建Class对象 Class obj = d1.getClass(); //以整数形式获取Dog的访问修饰符 int modifier = obj.getModifiers(); System.out.println("修饰符: " + Modifier.toString(modifier)); //找到Dog的超类 Class superClass = obj.getSuperclass(); System.out.println("Superclass: " + superClass.getName()); catch(Exception e) { e.printStackTrace(); }
输出结果
修饰符: public Superclass: Animal
该软件包java.lang.reflect提供了可用于操作类成员的类。例如,
方法类 - 提供有关类中方法的信息
字段类 - 提供有关类中字段的信息
构造函数类 - 提供有关类中构造函数的信息
我们可以使用Field类提供的各种方法检查和修改类的不同字段。
getFields() - 返回该类及其超类的所有公共字段
getDeclaredFields() - 返回类的所有字段
getModifier() - 以整数形式返回字段的修饰符
set(classObject,value) - 使用指定的值设置字段的值
get(classObject) - 获取字段的值
setAccessible(boolean) - 使私有字段可访问
注意: 如果我们知道字段名称,则可以使用
getField("fieldName") - 从类返回名称为 fieldName 的公共字段。
getDeclaredField
("fieldName")
- 从类返回名称为
fieldName
的字段。
import java.lang.Class; import java.lang.reflect.*; class Dog { public String type; class ReflectionDemo { public static void main(String[] args) { Dog d1 = new Dog(); //创建Class对象 Class obj = d1.getClass(); //操纵Dog类的公共字段type Field field1 = obj.getField("type"); //设置字段的值 field1.set(d1, "labrador"); //通过转换成字符串来获取字段的值 String typeValue = (String)field1.get(d1); System.out.println("type: " + typeValue); //获取类型的访问修饰符 int mod1 = field1.getModifiers(); String modifier1 = Modifier.toString(mod1); System.out.println("修饰符: " + modifier1); System.out.println(" "); catch(Exception e) { e.printStackTrace(); }
输出结果
type: labrador 修饰符: public
import java.lang.Class; import java.lang.reflect.*; class Dog { private String color; class ReflectionDemo { public static void main(String[] args) { try { Dog d1 = new Dog(); //创建类Class对象 Class obj = d1.getClass(); //访问私有字段 Field field2 = obj.getDeclaredField("color"); //使私有字段可访问 field2.setAccessible(true); //设置color值 field2.set(d1, "brown"); // get the value of type converting in String String colorValue = (String)field2.get(d1); System.out.println("color: " + colorValue); //获取color的访问修饰符 int mod2 = field2.getModifiers(); String modifier2 = Modifier.toString(mod2); System.out.println("modifier: " + modifier2); catch(Exception e) { e.printStackTrace(); }
输出结果
color: brown modifier: private
像字段一样,我们可以使用Method类提供的各种方法来检查类的不同方法。
getMethods() - 返回该类及其超类的所有公共方法
getDeclaredMethod() - 返回该类的所有方法
getName() - 返回方法的名称
getModifiers() - 以整数形式返回方法的访问修饰符
getReturnType() - 返回方法的返回类型
import java.lang.Class; import java.lang.reflect.*; class Dog { public void display() { System.out.println("I am a dog."); protected void eat() { System.out.println("I eat dog food."); private void makeSound() { System.out.println("Bark Bark"); class ReflectionDemo { public static void main(String[] args) { try { Dog d1 = new Dog(); //创建一个Class对象 Class obj = d1.getClass(); //使用getDeclaredMethod()获取所有方法 Method[] methods = obj.getDeclaredMethods(); //获取方法的名称 for(Method m : methods) { System.out.println("方法名称: " + m.getName()); //获取方法的访问修饰符 int modifier = m.getModifiers(); System.out.println("修饰符: " + Modifier.toString(modifier)); //获取方法的返回类型 System.out.println("Return Types: " + m.getReturnType()); System.out.println(" "); catch(Exception e) { e.printStackTrace(); }
输出结果
方法名称: display 修饰符: public Return type: void 方法名称: eat 修饰符: protected 返回类型: void 方法名称: makeSound 修饰符: private 返回类型: void
我们还可以使用Constructor类提供的各种方法检查类的不同构造函数。
getConstructors() - 返回该类的所有公共构造函数以及该类的超类
getDeclaredConstructor() -返回所有构造函数
getName() - 返回构造函数的名称
getModifiers() - 以整数形式返回构造函数的访问修饰符
getParameterCount() - 返回构造函数的参数数量
import java.lang.Class; import java.lang.reflect.*; class Dog { public Dog() { public Dog(int age) { private Dog(String sound, String type) { class ReflectionDemo { public static void main(String[] args) { try { Dog d1 = new Dog(); Class obj = d1.getClass(); //使用getDeclaredConstructor()获取一个类中的所有构造函数 Constructor[] constructors = obj.getDeclaredConstructors(); for(Constructor c : constructors) { //获取构造函数的名称 System.out.println("构造函数名称: " + c.getName()); //获取构造函数的访问修饰符 int modifier = c.getModifiers(); System.out.println("修饰符: " + Modifier.toString(modifier)); //获取构造函数中的参数数量 System.out.println("参数个数: " + c.getParameterCount()); catch(Exception e) { e.printStackTrace(); }
输出结果
构造函数名称: Dog 修饰符: public 参数个数: 0 构造函数名称: Dog 修饰符: public 参数个数: 1 构造函数名称: Dog 修饰符: private 参数个数: 2