用反射编写泛型数组

工具

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]

  

posted @ 2020-10-12 21:43  dedication  阅读(289)  评论(0编辑  收藏  举报