用反射编写泛型数组
工具
java.lang.reflect包中的Array类的方法。最关键的是Array类中的静态方法newInstance,它能够构造新数组。在调用它时必须提供两个参数,一个是数组的元素类型,一个是数组的长度。它的返回类型为object,而非object[]。
步骤
获取新数组元素类型:
① 首先获得a(需要处理的数组)数组的类对象
② 确认它是一个数组
③ 使用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; }
备注
入参类型Object 或者Object[]的区别是:Object允许直接传入基本类型的数组,而Object[]不能传入基本类型数组,必须是对象数组。因为基本类型的数组就是对象,而基本类型不是对象。
建议:应该将goodCopyOf的参数声明为Object类型,而不要声明为对象型数组(Object[])。整型数组类型int[]可以被转换成Object,但不能转换成对象数组。
错误写法
若想返回类型为object[]形式,则不能使用Array.newInstance创建数组,因为其返回类型为object。创建返回数组只能使用new Object[],这样做就丢掉了原始数组的类型。
public static Object[] badCopyOf(Object[] a, int newLength) { Object[] newArray = new Object[newLength]; System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newLength)); return newArray; }
用下面程序查看对应的class类型
package basic; import java.lang.reflect.Array; import java.util.Arrays; public class CopyOfTest { public static void main(String[] args) { int[] a = {1, 2, 3}; a = (int[]) goodCopyOf(a, 4); System.out.println(Arrays.toString(a)); Integer[] b = {1,3,5}; b = (Integer[]) CopyOf(b, 5); System.out.println(Arrays.toString(b)); b = (Integer[]) goodCopyOf(b, 5); System.out.println(Arrays.toString(b)); // b = (Integer[]) badCopyOf(b, 6); // java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer; Object[] o = badCopyOf(b, 6); System.out.println("badcopyof: 返回数组类型为" + o.getClass()); // class [Ljava.lang.Object; System.out.println(Arrays.toString(o)); } /** * 使用Array构建特定类型的数组 * @param a 可以是基本类型的数组 * @param newLength 新数组长度 * @return */ public static Object goodCopyOf(Object a, int newLength) { Class clazz = a.getClass(); System.out.println("goodCopyOf: 入参数组类型为 " + clazz); if (!clazz.isArray()) return null; int length = Array.getLength(a); Class componentType = clazz.getComponentType(); Object newArray = Array.newInstance(componentType, newLength); System.arraycopy(a, 0, newArray, 0, Math.min(length, newLength)); return newArray; } /** * 要使用Array构造特定类型的数组,返回类型不能写成object[] * @param a 不能是基本类型的数组 * @param newLength * @return */ public static Object CopyOf(Object[] a, int newLength) { Class clazz = a.getClass(); System.out.println("copyof: 入参数组类型为 " + clazz); if (!clazz.isArray()) return null; int length = Array.getLength(a); Class componentType = clazz.getComponentType(); System.out.println("copyof: 数组类型为 " + componentType); // 返回类型为object Object newArray = Array.newInstance(componentType, newLength); System.out.println("copyof: newArray.class " + newArray.getClass().getName()); System.arraycopy(a, 0, newArray, 0, Math.min(length, newLength)); return newArray; } public static Object[] badCopyOf(Object[] a, int newLength) { // 要返回object[]就丢失了a的原始类型 Object[] newArray = new Object[newLength]; System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newLength)); return newArray; } }
输出:
goodCopyOf: 入参数组类型为 class [I [1, 2, 3, 0] copyof: 入参数组类型为 class [Ljava.lang.Integer; copyof: 数组类型为 class java.lang.Integer copyof: newArray.class [Ljava.lang.Integer; [1, 3, 5, null, null] goodCopyOf: 入参数组类型为 class [Ljava.lang.Integer; [1, 3, 5, null, null] badcopyof: 返回数组类型为class [Ljava.lang.Object; [1, 3, 5, null, null, null]