Java反射中的Array类,java.lang.reflect包下的Array类

 

今天我们聊一聊java.lang.reflect包下的Array类,重点关注其中的newInstance方法。

1、Array类的简单使用

java.lang.reflect包下除了提供Method(方法)、Constructor(构造器)、Filed(成员变量)这三个类,还提供了Array类,Array对象可以代表所有的数组,可通过Array类来动态创建数组,该类提供了以下类方法:

  • static Object newInstance(Class<?> componentType, int... dimensions):创建指定元素类型、指定维度的数组。这里的dimensions是可变个数的。
  • static xxx getXxx(Object arr, int index):返回arr数组的第index位置元素。这里xxx表示基本数据类型,比如getChar,getInt;若数组元素是引用类型,该方法变为get((Object arr, int index)
  • static void setXxx((Object arr, int index, xxx val):向arr数组的第index位置插入val值

对于上述方法,下面有个非常简单的例子:

public class ReflectArrayTest {
    public static void main(String args[]) {
        try {
            // 创建长度为5,元素类型为String的数组
            Object arr = Array.newInstance(String.class, 5);

            Array.set(arr, 3, "ttt");
            Array.set(arr, 4, "fff");
            Object obj = Array.get(arr, 3);
            Object obj1 = Array.get(arr, 4);
        } catch (Throwable e) {
            System.err.println(e);
        }
    }
}

上述例子只是创建了简单的一维数组,利用Array.newInstance还可以创建多维数组。

2、newInstance()方法返回值并不是泛型

在上述例子虽然创建String数组,但是其返回值只是简单的Object对象,如果需要将arr对象当成String[]数组来用,就必须使用强转:String[] cast = (String []) arr;,但是强转是不安全的操作。而在反射中使用泛型Class<T>,可以有效避免强制类型转化。

观察Array的newInstance的方法签名,可以观察到奇怪的一点:

public static Object newInstance(Class<?> componentType, int... dimensions)

虽然方法签名中使用了Class<?>泛型,但实际上并没有真正利用泛型。如果将方法返回值改成如下形式:

public static <T> T[] newInstance(Class<T> componentType, int... dimensions)  这样就可以在调用该方法后无需强制类型转化了。不过改动了的这个方法只能暂时创建一维数组,就不能利用可变个数的参数优势了。

我们可以将Array的newInstance方法封装一下:

public class PackageArray {
    // 强转的时候,会有一个unchecked编译警告,使用该注解可以抑制这个警告信息
    @SuppressWarnings("unchecked")
    public static <T> T[] newInstance(Class<T> componentType, int length) {
        return (T[])Array.newInstance(componentType, length);
    }
}

封装后,调用PackageArray的newInstance类方法,就可直接获取到具体元素类型的数组对象了。

发布了48 篇原创文章 · 获赞 35 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/kqZhu/article/details/104216549