为什么泛型类数组的声明是正确的?

时间:2015-07-01 08:30:35

标签: java arrays generics

我们无法创建泛型类型的数组,这是一个众所周知的事实,所以我不打算在这里提供对JLS的正式引用。但我们可以声明这样的数组如下:

static <E> void reduce() {
    List<Integer>[] arr; //compiles fine
    E[] avv;             //compiles fine 
    avv = new E[10];       //doesn't compile
    arr = new List<Integer>[10]; //doesn't compile
}

有人知道这种声明的原因吗?

2 个答案:

答案 0 :(得分:2)

首先,我认为你的意思是

avv = new E[2];             //doesn't compile
arr = new List<Integer>[2]; //doesn't compile

在你方法的最后两行。您必须在创建新数组时指定数组的大小。但是,代码仍然无法编译。

阵列早于泛型。自Java的第一个版本以来,存在数组,而泛型仅在1.5版本中添加。为了打破旧代码,Java设计者决定在运行时擦除泛型类型:在运行时,类型参数被其上限替换。在您的情况下,在运行时,EObject相同。目前还不知道E是哪种类型。

这是一个问题,因为,数组元素类型在运行时不会被删除。 Integer[]String[]是不同的类型,即使在运行时也是如此。如果编写new E[2],Java运行时不知道它必须创建哪种类型的数组。它可以是String[]Integer[],也可以是任何其他数组类型。因此,您无法使用通用元素创建新数组。

仍允许使用具有泛型元素的数组作为类型,主要是为了在方法参数中使用它们:

<E> E doSomething(E[] param) { ... }

实际数组是在程序的另一部分中创建的,其类型是已知的。您可以使用

调用此方法
String result = doSomething(new String[2]);

例如。

答案 1 :(得分:1)

它允许您将泛型类型的数组作为方法参数传递。

例如:

public class Foo<T>
{
    public void bar (T[] arr) {}
}

...

Foo<String> foo = new Foo<String>();
String[] arr = {"aa","bb");
foo.bar (arr);

如果不允许T[],则方法签名必须为public void bar (Object[] arr),并且编译器允许您将任何类型的数组传递给该方法。