原创文章,转载请注明: 转载自工学1号馆
最近在学习java的反射机制,在《java核心系列11-反射》中,总结了java反射的,这篇文章将实战中体会java反射的强大和优势。
使用反射编写泛型数组代码
【例1】假设有这样一个需求:设计一个通用的程序,将一个任意类型的数组的长度扩大为指定的长度
比如将一个指定类型的对象数组扩展:
Employee[] a = new Employee[100]; a = Arrays.copyOf(a, 2 * a.length);
但是上面的代码并不具有通用性,接着看看下面的代码:
public static Object[] badCopyOf(Object[] a, int newLength) { Object[] newArray = new Object[newLength]; System.arraycopy(a, 0, newArray, 0, Math.max(a.length, newLength)); return newArray; }
上面的代码返回值的类型为Object[],在转换为 Employee的时候产生异常。
这里需要java.lang.reflect包中的Array类的一些方法,其中最关键的是newInstance,它能够构造新数组。
Object newArray = Array.newInstance(componentType, newLength);
这个方法中需要两个参数:数组的类型和长度。
这里的关键是获取数组的类型,这里分三步:
1、获取数组a的类对象
2、确定这个参数是数组
3、使用Class类的getComponentType方法确定数组对应的类型
看下面的代码:
public static Object goodCopyOf(Object a, int newLength) { Class cl = a.getClass(); if(!cl.isArray()) return null; Class componentType = cl.getComponentType(); int length = Array.getLength(a); Object newArray = Array.newInstance(componentType, newLength); System.arraycopy(a, 0, newArray, 0, Math.min(length, newLength)); return newArray; }
下面是完整的测试代码:
import java.lang.reflect.Array; import java.util.Arrays; public class test { public static Object[] badCopyOf(Object[] a, int newLength) { Object[] newArray = new Object[newLength]; System.arraycopy(a, 0, newArray, 0, Math.max(a.length, newLength)); return newArray; } public static Object goodCopyOf(Object a, int newLength) { Class cl = a.getClass(); if(!cl.isArray()) return null; Class componentType = cl.getComponentType(); int length = Array.getLength(a); Object newArray = Array.newInstance(componentType, newLength); System.arraycopy(a, 0, newArray, 0, Math.min(length, newLength)); return newArray; } public static void main(String[] args) { int[] a = {1, 2, 3}; a = (int[])goodCopyOf(a, 10); System.out.println(Arrays.toString(a)); String[] name = {"wu", "yu", "dong"}; name = (String[])goodCopyOf(name, 10); System.out.println(Arrays.toString(name)); //error! name = (String[])badCopyOf(name, 10); } }
【例2】打印通用对象,如果对象是数组,逐个元素打印,如果是其他的对象,则直接打印对象
private static void printObject(Object obj) { Class clazz = obj.getClass(); if(clazz.isArray()) { int len = Array.getLength(obj); for(int i = 0; i <len; i++) { System.out.println(Array.get(obj, i)); } } else { System.out.println(obj); } }
调用任意方法
利用反射技术还可以获取类的指定方法,使用Method对象实现C语言中的函数指针的所有操作。
import java.lang.reflect.Method; public class MethodPointerTest { public static void main(String[] args) throws Exception{ Method square = MethodPointerTest.class.getMethod("square", double.class); Method sqrt = MethodPointerTest.class.getMethod("sqrt", double.class); printTable(1, 10, 10, square); printTable(1, 10, 10, sqrt); } public static double square(double x) { return x * x; } public static double sqrt(double x) { return Math.sqrt(x); } public static void printTable(double from, double to, int n, Method f) { System.out.println(f); double dx = (to - from) / (n - 1); for(double x = from; x <= to; x += dx) { try { double y = (Double)f.invoke(null, x); System.out.printf("%10.4f | %10.4f%n", x, y); } catch (Exception e) { e.printStackTrace(); } } } }
第六行还可以换成:Method sqrt = Math.class.getMethod(“sqrt”, double.class); 同时把类中的静态方法sqrt删除
运行结果如下:
public static double MethodPointerTest.square(double)
1.0000 | 1.0000
2.0000 | 4.0000
3.0000 | 9.0000
4.0000 | 16.0000
5.0000 | 25.0000
6.0000 | 36.0000
7.0000 | 49.0000
8.0000 | 64.0000
9.0000 | 81.0000
10.0000 | 100.0000
public static double MethodPointerTest.sqrt(double)
1.0000 | 1.0000
2.0000 | 1.4142
3.0000 | 1.7321
4.0000 | 2.0000
5.0000 | 2.2361
6.0000 | 2.4495
7.0000 | 2.6458
8.0000 | 2.8284
9.0000 | 3.0000
10.0000 | 3.1623
Comments