8

我注意到在 Java 中Array.newInstance()返回Object,而不是T[]. 这是可以理解的,因为这种方法是在 Java 支持泛型类型之前引入的。

然而,令人惊讶的是,没有等效的通用版本。Java 7Arrays.copyOf不一样 - 它复制参数的内容,而不是创建一个新的虚拟数组(其中包含所有空对象)。

由于这似乎微不足道,有什么理由不将它添加到 JRE 中?还是我找不到?

更新

看来我将提供我自己的“微不足道”的实现来停止对这个问题的误解。

class MyArrayUtil {
    //Generic version for classes
    @SuppressWarnings("unchecked")
    public static <T> T[] newArrayOf(T[] t, int len){
        return (T[]) Array.newInstance(t.getClass().getComponentType(), len);
    }
    //For array of int
    public static int[] newArrayOf(int[] t, int len){
        return new int[len];
    }
    //For other primitive types...
}

我没有发布此代码作为答案,因为它不是问题的答案。问题是出于原因和/或现有代码,而不是如何实现。

更新

我已经更新了代码以使其类似于Arrays.copyOf,其优点是程序员可以简单地更改参数的类型以将代码调整为另一种类型。我也消除了Array.newInstance原始类型的使用。

4

3 回答 3

8

Guava 就提供了这样一个功能。这不是 Guava(或 Apache Commons)第一次提供 JDK 没有的常用助手,无论出于何种原因。

您可能知道这一点,但是对于将来偶然发现这一点的 googler 的一些背景知识:签名不能通用的原因是该方法在 Java 1.4中Array.newInstance 返回Object,因此为了向后兼容,该方法的原始版本应该也返回Object。如果它被泛化为:

<T> T[] newInstance(Class<T> componentType, int length)

...那么返回类型将是Object[],而不是Object。这将破坏向后兼容性,Java 设计人员一直非常努力地不这样做。

这些Arrays.copyOf方法只出现在 Java 1.6 中,因此不必担心向后兼容性。

于 2013-07-19T05:04:28.883 回答
4

不,您需要以一种或另一种方式将具体类型作为参数传递。正如你所提到的,Arrays.copyOf在行动中展示了这一点。

Class<T> type = determinteTheTypeSomehow();
return (T[]) Array.newInstance(type, length);
于 2013-07-19T03:15:16.897 回答
3

Array.newInstance()不能这样声明的基本原因<T> T[] newInstance(Class<T> class, int size)是因为它可以用来创建基元数组。例如,如果你传入int.class具有 typeClass<Integer>的 ,那么从声明中你会期望它返回一个Integer[]对象。但是,该函数实际上返回一个int[]对象,它不是 的子类型Integer[],因此它的类型错误。

当然,他们可以添加一个额外的方法,比如newReferenceArrayInstance()禁止原始类型(例如,在传递原始类型时抛出异常),因此可以安全地声明为 return T[]。但是,这似乎只是为了避免未经检查的强制转换而添加了一个完全冗余的方法。

于 2013-07-19T22:17:43.083 回答