使用反射编写泛型数组

发现问题

  我们都知道java.lang.reflect包中的Array类允许动态的创建数组。我们也知道Arrays的copyOf()可以扩展数组长度。那怎么实现这样的通用方法呢?

  假如说我们现在有一个Person[]数组a,想到Person[]可以转换为Object[],突然感觉问题就解决了。于是写下了下面的代码:

/**
 * @param a 源数组
 * @param newLength 新的数组长度
 */
public static object[] badCopyOf(Object[] a, int newLength){
    var newArray = new Object[newLength];
    System.arrayCopy(a, 0, newArray, 0, Math.min(a.length, newLength));
    return newArray;
}
复制代码

  然后再强制类型转换,但是报了一个ClassCastException,这个异常的意思是,不能从Object[]强制类型转换为Person[],这就出问题了,如果在其他地方使用这个方法就可能导致安全隐患。所以这种方法是不行的。

解决问题

  我们想到Array静态方法newInstance可以构造数组。

Array.newInstance(ComponentType componentType, int newLength);

第一个参数是数组内容类型,第二参数是新数组长度。所以说我们需要做两件事:

  1. 获得a的类对象(Class对象),确定a是一个数组,然后获得a的内容类型
  2. 获得源数组长度和newLength比较。

代码如下:

public static Object goodCopyOf(Object a, int newLength){
    Class class = a.getClass();
    if(!class.isArray())
        return null;
    Class componentType = class.getComponetType();
    int length = Array.getLength(a);
    Object newArray = Array.newStance(componentType, newLength);
    System.ArrayCopy(a, 0, newArray, 0, Math.min(length, newLength));
    return newArrary;
}
复制代码

  Array.newInstance方法根据ComponetType构建数组,所以返回的数组类型就是参数a的数组类型。
  可能有同学就要问了,“诶,你badCopyOf返回的是Object[],good返回的是Object,有什么讲究吗?”这你仔细想想,基础类型的数组不是Object[]子类,但是是Object的子类,所以为了适用性更好所以就用Object了。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享