原文: https://www.programiz.com/java-programming/reflection

在本教程中,我们将学习反射,这是 Java 编程中的一项功能,它使我们能够检查和修改类,方法等。

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


Java Class

在学习 Java 反射之前,我们需要了解一个名为Class的 Java 类。

Java 中有一个名为Class的类,可在运行时保留有关对象和类的所有信息。

Class的对象描述特定类的属性。 该对象用于执行反射。


创建名为Class的类对象

我们可以通过创建Class的对象

  • 使用forName()方法

forName()接受字符串参数(类的名称)并返回Class的对象。 返回的对象引用由字符串指定的类。 例如,

  1. Class Dog { }
  2. Class c1 = Class.forName("Dog");
  • 使用getClass()方法

getClass()方法使用特定类的对象创建Class的新对象。 例如,

  1. Dog d1 = new Dog()
  2. Class c1 = d1.getClass();
  • 使用.class

我们还可以使用.class扩展名创建Class的对象。 例如,

  1. Class c1 = Dog.class;

创建Class的对象后,我们可以使用这些对象进行反射。


获取接口

我们可以使用ClassgetInterfaces()方法来收集有关由该类实现的接口的信息。 此方法返回接口数组。

示例:获取接口

  1. import java.lang.Class;
  2. import java.lang.reflect.*;
  3. interface Animal {
  4. public void display();
  5. }
  6. interface Mammal {
  7. public void makeSound();
  8. }
  9. class Dog implements Animal, Mammal {
  10. public void display() {
  11. System.out.println("I am a dog.");
  12. }
  13. public void makeSound() {
  14. System.out.println("Bark bark");
  15. }
  16. }
  17. class ReflectionDemo {
  18. public static void main(String[] args) {
  19. try {
  20. // create an object of Dog class
  21. Dog d1 = new Dog();
  22. // create an object of Class using getClass()
  23. Class obj = d1.getClass();
  24. // find the interfaces implemented by Dog
  25. Class[] objInterface = obj.getInterfaces();
  26. for(Class c : objInterface) {
  27. // print the name of interfaces
  28. System.out.println("Interface Name: " + c.getName());
  29. }
  30. }
  31. catch(Exception e) {
  32. e.printStackTrace();
  33. }
  34. }
  35. }

输出

  1. Interface Name: Animal
  2. Interface Name: Mammal

获取超类和访问修饰符

Class的方法getSuperclass()可用于获取有关特定类超类的信息。

而且,Class提供了一种方法getModifier(),该方法以整数形式返回类的修饰符。

示例:获取超类和访问修饰符

  1. import java.lang.Class;
  2. import java.lang.reflect.*;
  3. interface Animal {
  4. public void display();
  5. }
  6. public class Dog implements Animal {
  7. public void display() {
  8. System.out.println("I am a dog.");
  9. }
  10. }
  11. class ReflectionDemo {
  12. public static void main(String[] args) {
  13. try {
  14. // create an object of Dog class
  15. Dog d1 = new Dog();
  16. // create an object of Class using getClass()
  17. Class obj = d1.getClass();
  18. // Get the access modifier of Dog in integer form
  19. int modifier = obj.getModifiers();
  20. System.out.println("Modifier: " + Modifier.toString(modifier));
  21. // Find the superclass of Dog
  22. Class superClass = obj.getSuperclass();
  23. System.out.println("Superclass: " + superClass.getName());
  24. }
  25. catch(Exception e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }

输出

  1. Modifier: public
  2. Superclass: Animal

要了解Class的更多方法,请访问 java.lang.Class


反射字段,方法和构造器

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

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

反射字段

我们可以使用Field类提供的各种方法来检查和修改类的不同字段。

  • getFields() - 返回该类及其超类的所有公共字段
  • getDeclaredFields() - 返回类的所有字段
  • getModifier() - 以整数形式返回字段的修饰符
  • set(classObject, value) - 使用指定的值设置字段的值
  • get(classObject) - 获取字段的值
  • setAccessible(boolean) - 使私有字段可访问

注意:如果我们知道字段名称,则可以使用

  • getField("fieldName") - 从类返回名称为fieldName的公共字段。
  • getDeclaredField("fieldName") - 从类返回名称为fieldName的字段。

要了解Field类的更多方法,请访问字段类

示例:访问公共字段

  1. import java.lang.Class;
  2. import java.lang.reflect.*;
  3. class Dog {
  4. public String type;
  5. }
  6. class ReflectionDemo {
  7. public static void main(String[] args) {
  8. try{
  9. Dog d1 = new Dog();
  10. // create an object of the class Class
  11. Class obj = d1.getClass();
  12. // manipulating the public field type of Dog
  13. Field field1 = obj.getField("type");
  14. // set the value of field
  15. field1.set(d1, "labrador");
  16. // get the value of field by converting in String
  17. String typeValue = (String)field1.get(d1);
  18. System.out.println("type: " + typeValue);
  19. // get the access modifier of type
  20. int mod1 = field1.getModifiers();
  21. String modifier1 = Modifier.toString(mod1);
  22. System.out.println("Modifier: " + modifier1);
  23. System.out.println(" ");
  24. }
  25. catch(Exception e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }

输出

  1. type: labrador
  2. Modifier: public

示例:访问私有字段

  1. import java.lang.Class;
  2. import java.lang.reflect.*;
  3. class Dog {
  4. private String color;
  5. }
  6. class ReflectionDemo {
  7. public static void main(String[] args) {
  8. try {
  9. Dog d1 = new Dog();
  10. // create an object of the class Class
  11. Class obj = d1.getClass();
  12. // accessing the private field
  13. Field field2 = obj.getDeclaredField("color");
  14. // making the private field accessible
  15. field2.setAccessible(true);
  16. // set the value of color
  17. field2.set(d1, "brown");
  18. // get the value of type converting in String
  19. String colorValue = (String)field2.get(d1);
  20. System.out.println("color: " + colorValue);
  21. // get the access modifier of color
  22. int mod2 = field2.getModifiers();
  23. String modifier2 = Modifier.toString(mod2);
  24. System.out.println("modifier: " + modifier2);
  25. }
  26. catch(Exception e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. }

输出

  1. color: brown
  2. modifier: private

Java 方法的反射

像字段一样,我们可以使用Method类提供的各种方法来检查类的不同方法。

  • getMethods() - 返回该类及其超类的所有公共方法
  • getDeclaredMethod() - 返回该类的所有方法
  • getName() - 返回方法的名称
  • getModifiers() - 以整数形式返回方法的访问修饰符
  • getReturnType() - 返回方法的返回类型

要了解有关Method类的更多方法的信息,请访问方法类

示例:方法反射

  1. import java.lang.Class;
  2. import java.lang.reflect.*;
  3. class Dog {
  4. public void display() {
  5. System.out.println("I am a dog.");
  6. }
  7. protected void eat() {
  8. System.out.println("I eat dog food.");
  9. }
  10. private void makeSound() {
  11. System.out.println("Bark Bark");
  12. }
  13. }
  14. class ReflectionDemo {
  15. public static void main(String[] args) {
  16. try {
  17. Dog d1 = new Dog();
  18. // create an object of Class
  19. Class obj = d1.getClass();
  20. // get all the methods using the getDeclaredMethod()
  21. Method[] methods = obj.getDeclaredMethods();
  22. // get the name of methods
  23. for(Method m : methods) {
  24. System.out.println("Method Name: " + m.getName());
  25. // get the access modifier of methods
  26. int modifier = m.getModifiers();
  27. System.out.println("Modifier: " + Modifier.toString(modifier));
  28. // get the return types of method
  29. System.out.println("Return Types: " + m.getReturnType());
  30. System.out.println(" ");
  31. }
  32. }
  33. catch(Exception e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. }

输出

  1. Method Name: display
  2. Modifier: public
  3. Return type: void
  4. Method Name: eat
  5. Modifier: protected
  6. Return Type: void
  7. Method Name: makeSound
  8. Modifier: private
  9. Return Type: void

构造器的反射

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

  • getConstructors() - 返回该类的所有公共构造器以及该类的超类
  • getDeclaredConstructor() - 返回所有构造器
  • getName() - 返回构造器的名称
  • getModifiers() - 以整数形式返回构造器的访问修饰符
  • getParameterCount() - 返回构造器的参数数量

要了解Constructor类的更多方法,请访问构造器类

示例:构造器反射

  1. import java.lang.Class;
  2. import java.lang.reflect.*;
  3. class Dog {
  4. public Dog() {
  5. }
  6. public Dog(int age) {
  7. }
  8. private Dog(String sound, String type) {
  9. }
  10. }
  11. class ReflectionDemo {
  12. public static void main(String[] args) {
  13. try {
  14. Dog d1 = new Dog();
  15. Class obj = d1.getClass();
  16. // get all the constructors in a class using getDeclaredConstructor()
  17. Constructor[] constructors = obj.getDeclaredConstructors();
  18. for(Constructor c : constructors) {
  19. // get names of constructors
  20. System.out.println("Constructor Name: " + c.getName());
  21. // get access modifier of constructors
  22. int modifier = c.getModifiers();
  23. System.out.println("Modifier: " + Modifier.toString(modifier));
  24. // get the number of parameters in constructors
  25. System.out.println("Parameters: " + c.getParameterCount());
  26. }
  27. }
  28. catch(Exception e) {
  29. e.printStackTrace();
  30. }
  31. }
  32. }

输出

  1. Constructor Name: Dog
  2. Modifier: public
  3. Parameters: 0
  4. Constructor Name: Dog
  5. Modifier: public
  6. Parameters: 1
  7. Constructor Name: Dog
  8. Modifier: private
  9. Parameters: 2