5

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

4 回答 4

3

toArray方法早于泛型的引入。的原始签名toArray取了一个任意的Object[].

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

于 2012-10-28T05:29:32.763 回答
0

当您调用时intArray = string.toArray(intArray);,您期望它构造 ArrayInteger并返回值,因此返回类型是T[]ieInteger[]在您的情况下。

调用这样的方法并不意味着您可以自动将 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)
于 2012-10-28T05:22:09.823 回答
0

当您问自己 in 数组的类型应该是什么时toArray(),第一个也是最明显的方法是将其限制T为的超类型E(包括 ifT与 相同E):这是有道理的——能够复制元素到比我们的集合更通用的元素类型的数组。然而,尽管乍一看这似乎是类型安全的(即在编译时检查,以便在运行时不会发生异常),但它并不是完全类型安全的——一个类型的变量T[]可以保存任何类型的数组,U[]其中U的子类型是T. 因此,ArrayStoreException即使我们限制T为的超类型E(并且,即使我们限制T为与E)。另外,很难以T只能是 的超类型的方式声明此方法E,因为 Java 不允许super类型参数的界限。

问题中的示例涉及 aT不是 的超类型E。为什么要允许这样做?这不是类型安全的,并且仅当集合的元素实际上是数组实际类型的子类型时才有效。但是,可以说这仍然不比T我们限制为 的超类型的情况更糟E,或者即使我们T与 相同E,因为如上所述,这些限制都不能使其成为类型安全的. ArrayStoreException无论你如何声明这个方法,都有可能得到。那么,如果没有更糟,为什么不让它尽可能通用呢?

于 2012-11-01T00:59:50.350 回答
-1

string.toArray(intArray)返回一个类型的数组String;但是,您希望它是一个 type 数组IntegerArrayStoreException由于类型不匹配,这将返回您提到的异常。

于 2012-10-28T05:31:31.233 回答