2011-05-17 82 views
2

以下代码将在toArray()处抛出ArrayStoreException。假如toArray需要V[]并且注册表Map键入的值为Map<String,String>,那么编译器是否应该没有发现错误并报告了类型冲突?编译器是否应该在泛型集合中发现这个错误?

private Map<String,Map<String,String>> registry; 

... 

registry=new TreeMap<String,Map<String,String>>(String.CASE_INSENSITIVE_ORDER)); 

... 

void removeTargets(String[] clsarr, String hdl) { 
     if(clsarr==null) { clsarr=registry.values().toArray(new String[0]); } 
    ... 
    } 

它看起来像一个编译器bug。

回答

3

不是编译器错误。可以说是一个图书馆的错误。

Collection.toArray()的类型是<T> T[] toArray(T[] a)。请注意,TtoArray方法的类型参数,与Collection的类型参数没有任何关系。

这个bug会被抓如果Collection.toArray签名是<T super E> T[] toArray(T[] a)但是这将使它很难使用,因为它是不合法的做new Map<String, String>[0] - 你得到一个“通用阵列创建”的错误。

+0

再一次,仿制药的支持“总比没有好,但留下了许多不足之处”。感谢您的解释。 – 2011-05-17 20:14:36

+0

@软件猴子。是啊。广泛使用的编程语言中的类型系统存在漏洞,导致错误可能漏过。这不是由于任何理论上的限制,而是由于Java数组类型的早期设计,它决定通过说'String []'是一个Object []'来解决方差问题,这使得它很难工作类型到试图正确处理差异的泛型类型系统中。 – 2011-05-17 20:31:02

2

号的toArray函数为:

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

返回包含此集合中的元素的阵列;返回数组的运行时类型是指定数组的运行时类型。

其中通用集合中的类型是E。所以你可以传入任何类型的变量。

这是一个klunky的设计,因为通用类型在编译时被擦除,所以在运行时无法返回适当类型的数组。这就是为什么你必须提供toArray呼叫中的类型。海事组织这是相当不雅 - 传递你想要的类型的数组 - 但Java并没有在这里提供任何方式来提供类型注释。