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
?
答案 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 T
与E
相同):这是有道理的 - 能够将元素复制到比我们的集合更通用的元素类型的数组中。但是,虽然这看起来是类型安全的(即在编译时检查,因此在运行时不会发生异常),但它并不完全是类型安全的 - 类型T[]
的变量可以保存任何类型的数组U[]
其中U
是T
的子类型。因此,即使我们将ArrayStoreException
限制为T
的超类型,我们仍然可以获得E
(如果我们限制T
,则甚至与E
)相同。另外,很难以T
只能是E
的超类型的方式声明此方法,因为Java不允许super
类型参数的边界。
问题中的示例涉及的T
不是E
的超类型。为什么要允许这样做?这不是类型安全的,只有当集合的元素实际上是数组实际类型的子类型时才有效。但是,可以认为,与我们将T
限制为E
的超类型,或者即使我们有T
的情况相比,这仍然不差与E
相同,因为如上所述,这些限制都不能使其类型安全。无论您如何声明此方法,都可以获得ArrayStoreException
。那么,为什么不尽可能地让它变得一般,如果不是更糟糕呢?
答案 3 :(得分:-1)
string.toArray(intArray)
返回String
类型的数组;但是,你希望它是一个Integer
类型的数组。由于类型不匹配,这将返回您提及的例外ArrayStoreException
。