五、反射:
1. Java的反射机制主要表现为四点:
1) 在运行中分析类的能力;
2) 在运行中查看对象;
3) 实现数组的操作代码;
4) 利用Method对象,这个对象很像C++中的函数指针。
注:Java的基于反射的应用主要用于一些工具类库的开发,在实际的应用程序开发中应用的场景较少。
2. 获取对象的名称(字符串形式) vs 通过对象的名称(字符串形式)创建对象实例,见如下代码:
2 //1. 通过对象获取其字符串表示的名称
3 Date d = new Date(); //or Class<? extends Date> c1 = d.class;
4 Class<? extends Date> c1 = d.getClass();
5 String className = c1.getName();
6
7 //2. 通过字符串形式的名称创建类实例。
8 className = "java.util." + className;
9 try {
10 Class c2 = Class.forName(className);
11 //这里用到的newInstance用于创建c2所表示的对象实例,但是必须要求待创建的类实例
12 //具有缺省构造函数(无参数),很明显newInstance调用并未传入任何参数用于构造对象。
13 Date d2 = (Date)c2.newInstance();
14 } catch (ClassNotFoundException e) {
15 e.printStackTrace();
16 } catch (InstantiationException e) {
17 e.printStackTrace();
18 } catch (IllegalAccessException e) {
19 e.printStackTrace();
20 }
21 }
如果需要通过调用带有参数的构造函数来创建对象实例,需要使用java.lang.reflect.Constructor对象来完成,见如下代码:
2 String className = "java.util.Date";
3 try {
4 Class c2 = Class.forName(className);
5 //找到只接受一个long类型参数的构造器
6 Constructor cc = c2.getConstructor(long.class);
7 long ll = 45L;
8 //将该Constructor期望的指定类型(long)的参数实例传入并构造Date对象。
9 Date dd = (Date)cc.newInstance(ll);
10 System.out.println("Date.toString = " + dd);
11 } catch (Exception e) {
12 e.printStackTrace();
13 }
14 }
3. 遍历一个未知类型的所有域、构造方法和域方法,见如下函数原型:
Field[] getFields(); 返回指定对象域字段数组,主要包含该类及其超类的所有公有(public)域。
Field[] getDeclaredFields();返回指定对象域字段数组,主要包含该类自身的所有域,包括private等。
Method[] getMethods(); 返回指定对象域方法数组,主要包含该类及其超类的所有公有(public)域方法。
Method[] getDeclaredMethods();返回指定对象域方法数组,主要包含该类自身的所有域方法,包括private等。
Constructor[] getConstructors(); 返回指定对象构造函数数组,主要包含该类所有公有(public)域构造器。
Constructor[] getDeclaredConstructors();返回指定对象构造函数数组,主要包含该类所有域构造器。
int getModifiers(); 返回一个用于描述构造器、方法或域的修饰符的整型数值,使用Modifier类中的静态方法可以协助分析这个返回值。
String getName(); 返回一个用于描述构造器、方法和域名的字符串。
Class[] getParameterTypes(); 返回一个用于描述参数类型的Class对象数组。
Class[] getReturnType(); 返回一个用于描述返回值类型的Class对象。
2 Constructor[] constructors = c1.getDeclaredConstructors();
3 for (Constructor c : constructors) {
4 String name = c.getName();
5 System.out.print(" ");
6 String modifiers = Modifier.toString(c.getModifiers());
7 if (modifiers.length() > 0)
8 System.out.print(modifiers + " ");
9 System.out.print(name + "(");
10
11 Class[] paramTypes = c.getParameterTypes();
12 for (int j = 0; j < paramTypes.length; ++j) {
13 if (j > 0)
14 System.out.print(",");
15 System.out.print(paramTypes[j].getName());
16 }
17 System.out.println(");");
18 }
19 }
20
21 private static void printMethods(Class c1) {
22 Method[] methods = c1.getDeclaredMethods();
23 for (Method m : methods) {
24 Class retType = m.getReturnType();
25 String name = m.getName();
26 System.out.print(" ");
27
28 String modifiers = Modifier.toString(m.getModifiers());
29 if (modifiers.length() > 0)
30 System.out.print(modifiers + " ");
31 System.out.print(retType.getName() + " " + name + "(");
32 Class[] paramTypes = m.getParameterTypes();
33 for (int j = 0; j < paramTypes.length; ++j) {
34 if (j > 0)
35 System.out.print(", ");
36 System.out.print(paramTypes[j].getName());
37 }
38 System.out.println(");");
39 }
40 }
41
42 private static void printFields(Class c1) {
43 Field[] fields = c1.getDeclaredFields();
44 for (Field f : fields) {
45 Class type = f.getType();
46 String name = f.getName();
47 System.out.print(" ");
48 String modifiers = Modifier.toString(f.getModifiers());
49 if (modifiers.length() > 0)
50 System.out.print(modifiers + " ");
51 System.out.println(type.getName() + " " + name + ";");
52 }
53 }
54
55 public static void main(String args[]) {
56 String name = "java.lang.Double";
57 try {
58 Class c1 = Class.forName(name);
59 Class superc1 = c1.getSuperclass();
60 String modifier = Modifier.toString(c1.getModifiers());
61 if (modifier.length() > 0)
62 System.out.print(modifier + " ");
63
64 System.out.print("class " + name);
65 if (superc1 != null && superc1 != Object.class)
66 System.out.print(" extends " + superc1.getName());
67
68 System.out.print("\n{\n");
69 printConstructors(c1);
70 System.out.println();
71 printMethods(c1);
72 System.out.println();
73 printFields(c1);
74 System.out.println("}");
75 } catch (Exception e) {
76 e.printStackTrace();
77 }
78 }
79 /* 输出结果如下:
80 public final class java.lang.Double extends java.lang.Number
81 {
82 public java.lang.Double(java.lang.String);
83 public java.lang.Double(double);
84
85 public boolean equals(java.lang.Object);
86 public java.lang.String toString();
87 public static java.lang.String toString(double);
88 public int hashCode();
89 public static native long doubleToRawLongBits(double);
90 public static long doubleToLongBits(double);
91 public static native double longBitsToDouble(long);
92 public int compareTo(java.lang.Double);
93 public volatile int compareTo(java.lang.Object);
94 public byte byteValue();
95 public short shortValue();
96 public int intValue();
97 public long longValue();
98 public float floatValue();
99 public double doubleValue();
100 public static java.lang.Double valueOf(double);
101 public static java.lang.Double valueOf(java.lang.String);
102 public static java.lang.String toHexString(double);
103 public static int compare(double, double);
104 public boolean isNaN();
105 public static boolean isNaN(double);
106 public boolean isInfinite();
107 public static boolean isInfinite(double);
108 public static double parseDouble(java.lang.String);
109
110 public static final double POSITIVE_INFINITY;
111 public static final double NEGATIVE_INFINITY;
112 public static final double NaN;
113 public static final double MAX_VALUE;
114 public static final double MIN_NORMAL;
115 public static final double MIN_VALUE;
116 public static final int MAX_EXPONENT;
117 public static final int MIN_EXPONENT;
118 public static final int SIZE;
119 public static final java.lang.Class TYPE;
120 private final double value;
121 private static final long serialVersionUID;
122 }
123 */