为什么<t> forArray隐藏了<e>的<e>?</e> </e> </t>

时间:2012-10-28 05:17:00

标签: java generics collections

toArray方法隐藏<E>传递给Collection<E>界面。以下是方法签名。

<T> T[] toArray(T[] a);

因为以下是可能的。并将结果导入ArrayStoreException

ArrayList<String> string = new ArrayList<String>();
string.add("1");
string.add("2");
Integer intArray[] = new Integer[2];
intArray = string.toArray(intArray);

我想知道为什么会做出这样的决定?为什么在设计API时允许这样的情况?无论如何,此代码会导致RuntimeException

4 个答案:

答案 0 :(得分:3)

toArray方法早于引入泛型。 toArray的原始签名采用了Object[]。{/ p>

这是泛型的唯一方法,即接受泛型之前允许的相同输入。但是,采用任意T[]的优点是它可以返回它传递的相同数组类型。

答案 1 :(得分:0)

当您调用intArray = string.toArray(intArray);时,您希望它构造Integer数组并返回值,因此返回类型为T[],即Integer[]

调用这样的方法并不意味着您可以自动将String list转换为Integer []。上面的方法调用将导致java.lang.ArrayStoreException

这样做是为了允许使用可转换类(基类/子类),例如下面:

  List<Integer> list = new ArrayList<Integer>();
  list.add(1);

  Integer[] intArray = new Integer[1];
  intArray = list.toArray(intArray); //Success

  Number [] numArray = new Number[1];
  numArray = list.toArray(numArray);//Success

  Double [] dubArray = new Double[1];
  dubArray = list.toArray(dubArray); //Failure(ArrayStoreException)

答案 2 :(得分:0)

当你问自己toArray()中数组的类型应该是什么时,第一个最明显的方法是将T限制为E的超类型(其中包括if TE相同):这是有道理的 - 能够将元素复制到比我们的集合更通用的元素类型的数组中。但是,虽然这看起来是类型安全的(即在编译时检查,因此在运行时不会发生异常),但它并不完全是类型安全的 - 类型T[]的变量可以保存任何类型的数组U[]其中UT的子类型。因此,即使我们将ArrayStoreException限制为T的超类型,我们仍然可以获得E(如果我们限制T,则甚至E)相同。另外,很难以T只能是E的超类型的方式声明此方法,因为Java不允许super类型参数的边界。

问题中的示例涉及的T不是E的超类型。为什么要允许这样做?这不是类型安全的,只有当集合的元素实际上是数组实际类型的子类型时才有效。但是,可以认为,与我们将T限制为E的超类型,或者即使我们有T的情况相比,这仍然不差E相同,因为如上所述,这些限制都不能使其类型安全。无论您如何声明此方法,都可以获得ArrayStoreException。那么,为什么不尽可能地让它变得一般,如果不是更糟糕呢?

答案 3 :(得分:-1)

string.toArray(intArray)返回String类型的数组;但是,你希望它是一个Integer类型的数组。由于类型不匹配,这将返回您提及的例外ArrayStoreException