最近在学习java的反射机制,总结了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
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
