Java基础系列(二十二):初识反射

2019 Java 开发者跳槽指南.pdf (吐血整理)….>>>

反射是什么

反射的作用用一句简单的话来将就是可以对代码进行操作的代码,这个特性经常在被用于创建JavaBean中,通常造轮子的人会用到这个特性,而应用程序员用到这个特性的场景则较少。

能够分析类能力的程序教叫做反射,简单来说来将就是可以对代码进行操作的代码。反射机制的功能极为强大,可以用来:

  1. 在运行时分析类的能力
  2. 在运行时查看对象
  3. 实现通用的数组操作代码
  4. 利用Method对象来实现方法

从获取Class类开始

在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。这个类的获取方式有以下三种:

1)使用Object类中的 getClass()方法来返回一个Class类的实例:

 

1
2
User user;
Class userClass = user.getClass();

2)我们可以使用Class类的 getName()方法来获取包含包名在内的类名。同样的,在已知这个名字的情况下,我们可以使用静态方法 forName()获得类名对应的Class对象:

1
2
3
4
5
6
Random generator = new Random();
Class randomClass = generator.getClass();
//className = "java.util.Random"
String className = randomClass.getName();
//第二种方式获取
Class newRandomClass = Class.forName(className);

3)获得Class类对象的第三种方法很简单,如果T是任意的Java类型(或void关键字),T.class将代表匹配的类对象。例如:

1
2
3
Class randomClass = Random.class;
Class intClass = int.class;
Class doubleClass = Double[].class;

如果我们想要创建一个类的实例,可以使用 newInstance()方法来动态创建:

1
2
String s = "java.util.Random";
Object m = Class.forName(s).newInstance();

利用反射分析类的能力

在java.lang.reflect包(反射库)中有三个类 Field, Method和 Constructor分别用于描述类的域,方法和构造器。这三个类都有一个叫做 getName()的方法,用于返回项目的名称。Filed类有一个 getType()方法,用于返回描述域所属类型的Class对象。Method和Constructor类有能够报告参数类型的方法,Method类还有一个可以报告返回类型的方法。

这三个类还有一个叫做 getModifiers()的方法,它将返回一个整型数值,用不同的位开关描述public和static这样的修饰符使用情况。另外,还可以利用java.lang.reflect包中的Modifier类的静态方法分析 gerModifiers()返回的整型数值。例如,可以使用Modifier类中的 isPublic()isPrivate()或 isFinal()判断方法或构造器是否是public,private或final。我们需要做的全部工作就是调用Modifier类的相应方法,并对返回的整型数值进行分析,另外,还可以利用 Modifier.toString()方法将修饰符打印出来。

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

下面我们来编写一个程序可以做到输入类名,然后打印出这个类的全部信息的作用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
public class ReflectionTest {
 
    public static void main(String[] args) {
 
        String name;
        if (args.length > 0) {
            name = args[0];
        } else {
            Scanner in = new Scanner(System.in);
            System.out.println("Enter class name (e.g. java.util.Date): ");
            name = in.next();
        }
 
        try {
            Class c1 = Class.forName(name);
            Class superclass = c1.getSuperclass();
            String modifiers = Modifier.toString(c1.getModifiers());
            if (modifiers.length() > 0 ) {
                System.out.print(modifiers + " ");
            }
            System.out.print("class " + name);
            if (superclass != null && superclass != Object.class) {
                System.out.print(" extends " + superclass.getName());
            }
            System.out.print("\n{\n");
            printConstructors(c1);
            System.out.println();
            printMethods(c1);
            System.out.println();
            printFields(c1);
            System.out.println("}");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.exit(0);
    }
 
    public static void printConstructors(Class c1) {
        Constructor[] constructors = c1.getDeclaredConstructors();
 
        for (Constructor constructor : constructors) {
            String name = constructor.getName();
            System.out.print("   ");
            String modifiers = Modifier.toString(constructor.getModifiers());
            if (modifiers.length() > 0) {
                System.out.print(modifiers + " ");
            }
            System.out.print(name + "(");
            Class[] paramTypes = constructor.getParameterTypes();
            for (int j = 0; j < paramTypes.length; j ++) {
                if (j > 0) {
                    System.out.print(", ");
                }
                System.out.println(paramTypes[j].getName());
            }
            System.out.println(");");
        }
    }
 
    public static void printMethods(Class c1) {
        Method[] methods = c1.getDeclaredMethods();
 
        for (Method method : methods) {
            Class returnType = method.getReturnType();
            String name = method.getName();
            System.out.println("   ");
            String modifiers = Modifier.toString(method.getModifiers());
            if (modifiers.length() > 0) {
                System.out.print(modifiers + " ");
            }
            System.out.println(returnType.getName() + " " + name + "(");
            Class[] paramTypes = method.getParameterTypes();
            for (int j = 0; j < paramTypes.length; j ++) {
                if (j > 0) {
                    System.out.print(", ");
                }
                System.out.print(paramTypes[j].getName());
            }
            System.out.println(");");
        }
    }
 
    public static void printFields(Class c1) {
        Field[] fields = c1.getDeclaredFields();
 
        for (Field field : fields) {
            Class type = field.getType();
            String name = field.getName();
            System.out.print("    ");
            String modifiers = Modifier.toString(field.getModifiers());
            if (modifiers.length() > 0 ) {
                System.out.print(modifiers + " ");
            }
            System.out.println(type.getName() + " " + name + ";");
        }
    }
}

当我们输入 java.lang.Double

程序输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public final class java.lang.Double extends java.lang.Number
{
   public java.lang.Double(double);
   public java.lang.Double(java.lang.String);
 
 
    public boolean equals(java.lang.Object);
 
    public static java.lang.String toString(double);
 
    public java.lang.String toString();
 
    public int hashCode();
 
    public static int hashCode(double);
 
    public static double min(double, double);
 
    public static double max(double, double);
 
    public static native long doubleToRawLongBits(double);
 
    public static long doubleToLongBits(double);
 
    public static native double longBitsToDouble(long);
 
    public volatile int compareTo(java.lang.Object);
 
    public int compareTo(java.lang.Double);
 
    public byte byteValue();
 
    public short shortValue();
 
    public int intValue();
 
    public long longValue();
 
    public float floatValue();
 
    public double doubleValue();
 
    public static java.lang.Double valueOf(java.lang.String);
 
    public static java.lang.Double valueOf(double);
 
    public static java.lang.String toHexString(double);
 
    public static int compare(double, double);
 
    public static boolean isNaN(double);
 
    public boolean isNaN();
 
    public static boolean isFinite(double);
 
    public static boolean isInfinite(double);
 
    public boolean isInfinite();
 
    public static double sum(double, double);
 
    public static double parseDouble(java.lang.String);
 
    public static final double POSITIVE_INFINITY;
    public static final double NEGATIVE_INFINITY;
    public static final double NaN;
    public static final double MAX_VALUE;
    public static final double MIN_NORMAL;
    public static final double MIN_VALUE;
    public static final int MAX_EXPONENT;
    public static final int MIN_EXPONENT;
    public static final int SIZE;
    public static final int BYTES;
    public static final java.lang.Class TYPE;
    private final double value;
    private static final long serialVersionUID;
}

关于反射的更多内容,我们在下一节中揭晓。