Seb*_*ber 6 java generics scjp java-ee
在回答有关此问题的问题时:https://stackoverflow.com/a/9872630/82609
我试着做以下事情:
Comparator<String>[] comparators = new Comparator[] {...};
Run Code Online (Sandbox Code Playgroud)
有用!但以下不是:
Comparator<String>[] comparators = new Comparator<String>[] {...};
Run Code Online (Sandbox Code Playgroud)
在相关问题上,我做了以下假设:
我想这是因为最初的数组合约可能是这样的:
如果你创建一个X类型的数组,你将永远不能在其中放入任何IS-NOT-AN X.如果你尝试,你会得到一个ArrayStoreException
因此,允许使用泛型创建的数组会导致不同的规则,例如:
如果你创建一个类型的数组
X<Y>,你将永远不能放置任何IS-NOT-AN X.如果你尝试,你将得到一个ArrayStoreException.但是你可以添加两个X<Y>和X<Z>对象,因为类型擦除!
但是考虑一下,它真的会成为一个问题:
Comparator<String>[] comparators = new Comparator<String>[] {...};
Run Code Online (Sandbox Code Playgroud)
我真的不明白为什么它不可能,因为使用这样的东西会:
最后,我们可以使用具有泛型类型引用的数组,并且由于不可能创建具有泛型类型的数组,我想很多人甚至不知道它是可能的.
我只是想知道是否有人知道这个选择背后的原因?
这有点像强迫人们使用List<String> = new ArrayList();而不是使用List<String> = new ArrayList<String>();
dimitrisli你从约书亚布洛赫的着名书中给出了一个很好的例子.正如您/他解释的那样,使用泛型数组+协方差并且可能导致ClassCastException是危险的,而我们期望使用协方差从数组中获取ArrayStoreException.
但请注意以下内容仍然合法且导致相同:
List<String>[] stringLists = new List[1];
List<Integer> intList = Arrays.asList(42);
Object[] objects = stringLists;
objects[0] = intList;
String s = stringLists[0].get(0);
Run Code Online (Sandbox Code Playgroud)
但是,它会在编译时生成未经检查的强制转换警告,正如您所提到的,在运行时会产生ClassCastException.
我明白你的观点(从实际意义上讲,我基本上同意),但我认为存在差异,导致了当前的情况。
正如您所提到的,擦除意味着通用参数在运行时不可用,因此在编译时检查类型(无论是 aList<String>还是您的Comparator<String>[])。重要的是,这是基于变量的通用参数。
另一方面,数组在插入时会在运行时检查其参数的类型,因此ArrayStoreException如果误用(通常是由于滥用协方差),它们可能会抛出异常。因此,数组需要能够在内部执行这两个要点检查,当然它们无法在运行时检查通用参数。因此,实例化泛型数组是没有意义的,因为该数组必须完全忽略泛型参数,这充其量只会产生误导。
也就是说,将这样的数组分配给参数化引用确实有意义,因为这样编译器就可以执行通用检查。您的想法是正确的,这涵盖了所有基础并确保检查泛型类型(只要变量参数化正确)。
这种选择背后的根本原因,以及为什么数组在这方面与集合不同,是数组需要在插入时实际检查其参数的类型,而集合只是接受您的话并允许类型错误会冒泡到ClassCastException以后。
| 归档时间: |
|
| 查看次数: |
581 次 |
| 最近记录: |