4. 通过反射编写泛型数组代码,见如下代码比较:
1 static Object[] badArrayGrow(Object[] a) {
2 int newLength = a.length * 11 / 10 + 10;
3 //该对象数组的在创建时是基于Object的,所以返回后,
4 //再装回其他类型数组时将会抛出ClassCastException的异常。
5 Object[] newArray = new Object[newLength];
6 System.arraycopy(a,0,newArray,0,a.length);
7 return newArray;
8 }
9
10 static Object goodArrayGrow(Object a) {//这里的参数务必为Object,而不是Object[]
11 Class c1 = a.getClass();
12 if (!c1.isArray())
13 return null;
14 //这里用于获取数组成员的类型
15 Class componentType = c1.getComponentType();
16 //获取数组的长度。
17 int length = Array.getLength(a);
18 int newLength = length * 11 / 10 + 10;
19 //通过数组成员的类型和新的长度值来创建一个和参数类型相同的数组,
20 //并增加他的空间,最后再返回。
21 Object newArray = Array.newInstance(componentType,newLength);
22 System.arraycopy(a,0,newArray,0,length);
23 return newArray;
2 int newLength = a.length * 11 / 10 + 10;
3 //该对象数组的在创建时是基于Object的,所以返回后,
4 //再装回其他类型数组时将会抛出ClassCastException的异常。
5 Object[] newArray = new Object[newLength];
6 System.arraycopy(a,0,newArray,0,a.length);
7 return newArray;
8 }
9
10 static Object goodArrayGrow(Object a) {//这里的参数务必为Object,而不是Object[]
11 Class c1 = a.getClass();
12 if (!c1.isArray())
13 return null;
14 //这里用于获取数组成员的类型
15 Class componentType = c1.getComponentType();
16 //获取数组的长度。
17 int length = Array.getLength(a);
18 int newLength = length * 11 / 10 + 10;
19 //通过数组成员的类型和新的长度值来创建一个和参数类型相同的数组,
20 //并增加他的空间,最后再返回。
21 Object newArray = Array.newInstance(componentType,newLength);
22 System.arraycopy(a,0,newArray,0,length);
23 return newArray;
24 }
25
5. 在运行时使用反射的对象或动态调用反射之后的方法。
1) 获取域字段和设置域字段:
1 public void testField() {
2 Employee harry = new Employee("Harry Hacker",35000,10);
3 Class c1 = harry.getClass();
4 Field f = c1.getDeclaredField("name");
5 //由于name字段有可能是Employee类的私有域字段,如果直接调用会致使JVM
6 //抛出安全异常,为了避免该异常的发生,需要调用下面的语句来得以保证。
7 f.setAccessible(true);
8 Object v = f.get(harry);
9 System.out.println(v);
10 }
2 Employee harry = new Employee("Harry Hacker",35000,10);
3 Class c1 = harry.getClass();
4 Field f = c1.getDeclaredField("name");
5 //由于name字段有可能是Employee类的私有域字段,如果直接调用会致使JVM
6 //抛出安全异常,为了避免该异常的发生,需要调用下面的语句来得以保证。
7 f.setAccessible(true);
8 Object v = f.get(harry);
9 System.out.println(v);
10 }
2) 通过Method的invoke函数动态调用反射后的方法:
该方式有些类似于C#的委托(delegate)和C++的函数指针。
1 public int add(int param1, int param2) {
2 return param1 + param2;
3 }
4
5 public static void main(String[] args) throws Exception {
6 Class classType = MyTest.class;
7 Object myTest = classType.newInstance();
8 Method addMethod = classType.getMethod("add",int.class,int.class);
9 //如果add为静态方法,这里的第一个参数传null
10 Object result = addMethod.invoke(myTest, 100,200);
11 System.out.println(result);
12 }
2 return param1 + param2;
3 }
4
5 public static void main(String[] args) throws Exception {
6 Class classType = MyTest.class;
7 Object myTest = classType.newInstance();
8 Method addMethod = classType.getMethod("add",int.class,int.class);
9 //如果add为静态方法,这里的第一个参数传null
10 Object result = addMethod.invoke(myTest, 100,200);
11 System.out.println(result);
12 }
6. C++自身并没有提供像Java这样完备的反射机制,只是提供了非常简单的动态类型信息,如type_info和typeid。然而在一些C++的第三方框架类库中提供了类似的功能,如MFC、QT。其中MFC是通过宏的方式实现,QT是通过自己的预编译实现。在目前的主流开发语言中,也只有C#提供的反射机制可以和Java的相提并论。