> For the complete documentation index, see [llms.txt](https://3385706034.gitbook.io/note/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://3385706034.gitbook.io/note/java-reflection.md).

# 利用反射分析类的能力

## 检查类的结构

反射机制最重要的内容 - 检查类的结构.

| Class             | Description                                                                                                                              |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| AccessibleObject  | The **AccessibleObject** class is the base class for **Field**, **Method**, and **Constructor** objects (known as reflected objects).    |
| Array             | The **Array** class provides static methods to dynamically create and access Java arrays.                                                |
| Constructor\\     | **Constructor** provides information about, and access to, a single constructor for a class.                                             |
| Executable        | A shared superclass for the common functionality of **Method** and **Constructor**.                                                      |
| Field             | A **Field** provides information about, and dynamic access to, a single field of a class or an interface.                                |
| Method            | A **Method** provides information about, and access to, a single method on a class or interface.                                         |
| Modifier          | The Modifier class provides **static** methods and constants to decode class and member access modifiers.                                |
| Parameter         | Information about method parameters.                                                                                                     |
| Proxy             | **Proxy** provides static methods for creating objects that act like instances of interfaces but allow for customized method invocation. |
| ReflectPermission | The Permission class for reflective operations.                                                                                          |

在 `java.lang.reflect` 包中有三个类 `Field`, `Method` 和 `Constructor` 分别用于描述类的域,方法和构造器.这三个类都有一个叫做 `getName` 的方法,用来返回项目的名称.`Fleld` 类有一个 `getType` 方法,用来返回描述域所属类型的 `Class` 对象.`Method` 和 `Constructor` 类有能够报告参数类型的方法,`Method` 类还有一个可以报告返回类型的方法.这三个类还有一个叫做 `getModifiers` 的方法,它将返回一个整型数值,用不同的位开关描述 `public` 和 `static` 这样的修饰符使用状况.另外,还可以利用 `java.lang.reflect` 包中的 `Modifier` 类的静态方法分析 `getModifiers` 返回的整型数值.例如,可以使用 `Modifier` 类中的 `isPublic` , `isPrivate` 或 `isFinal`判断方法或构造器是否是 `public` , `private` 或 `final`.我们需要做的全部工作就是调用 `Modifier` 类的相应方法,并对返回的整型数值进行分析,另外,还可以利用 `Modifier.toString` 方法将修饰符打印出来.

`Class` 类中的 `getFields` , `getMethods` 和 `getConstructors` 方法将分别返回类提供的 `public` 域,方法和构造器数组,其中包括超类的公有成员.`Class` 类的 `getDeclareFields`,`getDeclareMethods` 和 `getDeclaredConstructors` 方法将分别返回类中声明的全部域,方法和构造器,其中包括私有和受保护成员,但不包括超类的成员 .

下面代码显示了如何打印一个类的全部信息的方法.这个程序将提醒用户输入类名,然后输出类中所有的方法和构造器的签名,以及全部域名.假如输入

```java
java.util.Date
```

程序输出:

```
publicclass java.util.Date
{
   public java.util.Date(java.lang.String);
   public java.util.Date(int, int, int, int, int, int);
   public java.util.Date(int, int, int, int, int);
   public java.util.Date();
   public java.util.Date(long);
   public java.util.Date(int, int, int);

   public boolean equals(java.lang.Object);
   public java.lang.String toString();
   public int hashCode();
   public java.lang.Object clone();
   public volatile int compareTo(java.lang.Object);
   public int compareTo(java.util.Date);
   public static java.util.Date from(java.time.Instant);
   private void readObject(java.io.ObjectInputStream);
   private void writeObject(java.io.ObjectOutputStream);
   private final sun.util.calendar.BaseCalendar$Date normalize(sun.util.calendar.BaseCalendar$Date);
   private final sun.util.calendar.BaseCalendar$Date normalize();
   public boolean before(java.util.Date);
   public boolean after(java.util.Date);
   public static long parse(java.lang.String);
   public int getSeconds();
   public java.time.Instant toInstant();
   public static long UTC(int, int, int, int, int, int);
   public int getYear();
   public long getTime();
   public void setTime(long);
   static final long getMillisOf(java.util.Date);
   public void setDate(int);
   public int getMonth();
   private final sun.util.calendar.BaseCalendar$Date getCalendarDate();
   public void setHours(int);
   public int getHours();
   public int getMinutes();
   public void setMonth(int);
   public void setMinutes(int);
   public void setSeconds(int);
   public void setYear(int);
   private static final sun.util.calendar.BaseCalendar getCalendarSystem(long);
   private static final sun.util.calendar.BaseCalendar getCalendarSystem(int);
   private static final sun.util.calendar.BaseCalendar getCalendarSystem(sun.util.calendar.BaseCalendar$Date);
   private final long getTimeImpl();
   private static final java.lang.StringBuilder convertToAbbr(java.lang.StringBuilder, java.lang.String);
   private static final synchronized sun.util.calendar.BaseCalendar getJulianCalendar();
   public int getDate();
   public int getDay();
   public java.lang.String toLocaleString();
   public java.lang.String toGMTString();
   public int getTimezoneOffset();

  public java.util.Date(java.lang.String);
  public java.util.Date(int, int, int, int, int, int);
  public java.util.Date(int, int, int, int, int);
  public java.util.Date();
  public java.util.Date(long);
  public java.util.Date(int, int, int);
}

Process finished with exit code 0
```

## 代码

```java
package reflection;

import java.util.*;
import java.lang.reflect.*;

public class ReflectionTest {
    public static void main(String[] args) {
        // read class name from command line args or user input
        String name;
        if(args.length > 0) name = args[0];
        else
        {
            Scanner in = new Scanner(System.in);
            System.out.println("输入一个类的名称 (例如 java.util.Date): ");
            name = in.next();
        }

        try {
            // Print class name and superclass name (if != Object)
            Class cl = Class.forName(name);
            Class supercl = cl.getSuperclass();
            String modifiers = Modifier.toString(cl.getModifiers());
            if(modifiers.length() > 0) System.out.print(modifiers + "");
            System.out.print("class " + name);
            if(supercl != null && supercl != Object.class) System.out.printf(" extends " + supercl.getName());
            System.out.printf("\n{\n");
            printConstructors(cl);
            System.out.println();
            printMethods(cl);
            System.out.println();
            printFields(cl);
            System.out.println("}");
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        System.exit(0);
    }

    /**
     * Prints all constructors of a class
     * @param cl a class
     */
    private static void printFields(Class cl) {
        Constructor[] constructors = cl.getDeclaredConstructors();

        for (Constructor c : constructors)
        {
            String name = c.getName();
            System.out.printf("  ");
            String modifiers = Modifier.toString(c.getModifiers());
            if(modifiers.length() > 0) System.out.printf(modifiers + " ");
            System.out.printf(name + "(");

            // print parameter types
            Class[] paramTypes = c.getParameterTypes();
            for (int j = 0; j < paramTypes.length; j++)
            {
                if(j > 0) System.out.printf(", ");
                System.out.printf(paramTypes[j].getName());
            }
            System.out.println(");");
        }
    }

    /**
     * Prints all methods of a class
     * @param cl a class
     */
    public static void printMethods(Class cl)
    {
        Method[] methods = cl.getDeclaredMethods();

        for (Method m : methods)
        {
            Class retType = m.getReturnType();
            String name = m.getName();

            System.out.print("   ");
            // print modifiers, return type and method name
            String modifiers = Modifier.toString(m.getModifiers());
            if (modifiers.length() > 0) System.out.print(modifiers + " ");
            System.out.print(retType.getName() + " " + name + "(");

            // print parameter types
            Class[] paramTypes = m.getParameterTypes();
            for (int j = 0; j < paramTypes.length; j++)
            {
                if (j > 0) System.out.print(", ");
                System.out.print(paramTypes[j].getName());
            }
            System.out.println(");");
        }
    }

    /**
     * Prints all constructors of a class
     * @param cl a class
     */
    public static void printConstructors(Class cl)
    {
        Constructor[] constructors = cl.getDeclaredConstructors();

        for (Constructor c : constructors)
        {
            String name = c.getName();
            System.out.print("   ");
            String modifiers = Modifier.toString(c.getModifiers());
            if (modifiers.length() > 0) System.out.print(modifiers + " ");
            System.out.print(name + "(");

            // print parameter types
            Class[] paramTypes = c.getParameterTypes();
            for (int j = 0; j < paramTypes.length; j++)
            {
                if (j > 0) System.out.print(", ");
                System.out.print(paramTypes[j].getName());
            }
            System.out.println(");");
        }
    }
}
```
