# Java 反射

> 原文： [https://www.programiz.com/java-programming/reflection](https://www.programiz.com/java-programming/reflection)

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

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

* * *

## Java `Class`类

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

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

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

* * *

## 创建名为`Class`的类对象

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

*   **使用`forName()`方法**

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

```java
Class Dog {  }
Class c1 = Class.forName("Dog"); 
```

*   **使用`getClass()`方法**

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

```java
Dog d1 = new Dog()
Class c1 = d1.getClass(); 
```

*   **使用`.class`**

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

```java
Class c1 = Dog.class; 
```

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

* * *

## 获取接口

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

### 示例：获取接口

```java
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 {
          // create an object of Dog class
          Dog d1 = new Dog();

          // create an object of Class using getClass()
          Class obj = d1.getClass();

          // find the interfaces implemented by Dog
          Class[] objInterface = obj.getInterfaces();
          for(Class c : objInterface) {

              // print the name of interfaces
              System.out.println("Interface Name: " + c.getName());
          }
      }

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

**输出**

```java
Interface Name: Animal
Interface Name: Mammal 
```

* * *

## 获取超类和访问修饰符

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

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

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

```java
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 {
           // create an object of Dog class
           Dog d1 = new Dog();

           // create an object of Class using getClass()
           Class obj = d1.getClass();

          // Get the access modifier of Dog in integer form
           int modifier = obj.getModifiers();
           System.out.println("Modifier: " + Modifier.toString(modifier));

           // Find the superclass of Dog
           Class superClass = obj.getSuperclass();
           System.out.println("Superclass: " + superClass.getName());
       }

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

**输出**

```java
Modifier: public
Superclass: Animal 
```

要了解`Class`的更多方法，请访问 [java.lang.Class](https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html) 。

* * *

## 反射字段，方法和构造器

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

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

* * *

## 反射字段

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

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

**注意**：如果我们知道字段名称，则可以使用

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

要了解`Field`类的更多方法，请访问[字段类](https://docs.oracle.com/javase/8/docs/api/index.html)。

### 示例：访问公共字段

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

class Dog {
  public String type;
}

class ReflectionDemo {
  public static void main(String[] args) {
     try{
         Dog d1 = new Dog();
        // create an object of the class Class
         Class obj = d1.getClass();

        // manipulating the public field type of Dog     
         Field field1 = obj.getField("type");
        // set the value of field
         field1.set(d1, "labrador");
       // get the value of field by converting in String
         String typeValue = (String)field1.get(d1);
         System.out.println("type: " + typeValue);

         // get the access modifier of type
         int mod1 = field1.getModifiers();
         String modifier1 = Modifier.toString(mod1);
         System.out.println("Modifier: " + modifier1);
         System.out.println(" ");
     }
     catch(Exception e) {
         e.printStackTrace();
     }
  }
} 
```

**输出**：

```java
type: labrador
Modifier: public 
```

### 示例：访问私有字段

```java
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();
      // create an object of the class Class
      Class obj = d1.getClass();

      // accessing the private field
      Field field2 = obj.getDeclaredField("color");

      // making the private field accessible
      field2.setAccessible(true);
      // set the value of color
      field2.set(d1, "brown");
      // get the value of type converting in String
      String colorValue = (String)field2.get(d1);
      System.out.println("color: " + colorValue);

      // get the access modifier of color
      int mod2 = field2.getModifiers();
      String modifier2 = Modifier.toString(mod2);
      System.out.println("modifier: " + modifier2);
   }
   catch(Exception e) {
      e.printStackTrace();
   }
 }
} 
```

**输出**：

```java
color: brown
modifier: private 
```

* * *

## Java 方法的反射

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

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

要了解有关`Method`类的更多方法的信息，请访问[方法类](https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html)。

### 示例：方法反射

```java
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();

          // create an object of Class
          Class obj = d1.getClass();

          // get all the methods using the getDeclaredMethod()
          Method[] methods = obj.getDeclaredMethods();

          // get the name of methods
          for(Method m : methods) {

             System.out.println("Method Name: " + m.getName());

             // get the access modifier of methods
             int modifier = m.getModifiers();
             System.out.println("Modifier: " + Modifier.toString(modifier));

             // get the return types of method
             System.out.println("Return Types: " + m.getReturnType());
             System.out.println(" ");
          }
       }
       catch(Exception e) {
           e.printStackTrace();
       }
   }
} 
```

**输出**：

```java
Method Name: display
Modifier: public
Return type: void

Method Name: eat
Modifier: protected
Return Type: void

Method Name: makeSound
Modifier: private
Return Type: void 
```

* * *

## 构造器的反射

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

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

要了解`Constructor`类的更多方法，请访问[构造器类](https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Constructor.html)

### 示例：构造器反射

```java
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();

           // get all the constructors in a class using getDeclaredConstructor()
           Constructor[] constructors = obj.getDeclaredConstructors();

           for(Constructor c : constructors) {
           // get names of constructors
               System.out.println("Constructor Name: " + c.getName());

           // get access modifier of constructors
               int modifier = c.getModifiers();
               System.out.println("Modifier: " + Modifier.toString(modifier));

           // get the number of parameters in constructors
               System.out.println("Parameters: " + c.getParameterCount());
          }
       }
       catch(Exception e) {
           e.printStackTrace();
       }
    }
} 
```

**输出**：

```java
Constructor Name: Dog
Modifier: public
Parameters: 0

Constructor Name: Dog
Modifier: public
Parameters: 1

Constructor Name: Dog
Modifier: private
Parameters: 2 
```