利用Java反射动态创建数组

5.7 反射

5.7.6 用反射设计通用数组的代码

java.lang.reflect包中的Array类允许我们动态的创建数组,我们尝试用这个特性自己实现一下Arrays(java.util.Arrays)的copyOf方法。

第一版的代码为

public static Object[] badCopyOf(Object[] a, int newLength) // not useful 
{
	var newArray = new Object[newLength];
	System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newLength)); 
	return newArray;
}

这个代码是存在问题的,这个方法返回的Object[](Object数组对象)没法转换为我们需要的对象,例如之前的Employee。这是因为Java的数组对象会记录它的入口类型,即我们使用new创建这个数组时使用的类型,这就导致了最初以Employee[]创建的数组能转换为Object[],并且再这之后还能再一次的转换为Employee[]。但是以Object[]创建的数组不能转换为Employee

我们可以使用Array的一个静态方法newInstance构造数组来解决这个问题。

于是有了第二版的代码:

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;
}

你可能已经注意到了方法参数也有一些变化,即原本的Object[] a变为了Object a这是因为我们的方法需要兼容Java的基本数据类型(int, double, long ...),这个基本数据类型的数组是可以转换为Object对象的,但是没办法转换为一个Object对象的数组(Object[])。

也许你会对这份代码产生一点违和感(恭喜,对感受代码的直觉能力蛮高),getComponent方法是属于Class的,而getLength方法是属于Array的。至于为什么是这样,我也不知道了……

上一篇:GO编程模式学习笔记:MAP-REDUCE


下一篇:C#练习题答案: 数字对【难度:1级】--景越C#经典编程题库,1000道C#基础练习题等你来挑战