为什么“集合”不简单地视为“集合<”>

考虑以下 API 方法,该方法取自 Shiro 的组织.apache.shiro.主题.Principal 收集接口,但也可能存在于其他库中:

Collection fromRealm(String realmName);

是的,即使现在仍然有使用原始类型的库,可能是为了保持Java 1.5之前的兼容性?!

如果我现在想将此方法与流或可选选项一起使用,如下所示:

principals.fromRealm(realmName).stream().collect(Collectors.toSet());

我收到有关未选中转换和使用原始类型的警告,并且我更喜欢使用参数化类型。

日蚀:

类型安全:方法收集(收集器)属于原始类型流。对泛型类型 Stream<T> 的引用应参数化

爪哇:

注意:泛型测试.java使用未经检查或不安全的操作。

由于我无法更改API方法的签名以摆脱此警告,因此我可以注释或简单地转换为如下所示:@SuppressWarnings("unchecked")Collection<?>

((Collection<?>) principals.fromRealm(realmName)).stream().collect(Collectors.toSet());

由于这种转换当然总是有效的,我想知道为什么编译器不是简单地对待而是警告这种情况。添加批注或强制转换不会稍微改进代码,但会降低可读性,甚至可能隐藏有关使用非参数化类型的实际有效警告。CollectionCollection<?>



largeQ
浏览 83回答 4
4回答

莫回无

原因很简单:您可以从与 从 相同的方式读取 s。但是你不能将s添加到a(编译器禁止这样做),而在a中你可以。ObjectCollection<?>CollectionObjectCollection<?>Collection如果在Java 5发布后,编译器已经将每个翻译成,那么以前编写的代码将不再编译,从而破坏向后兼容性。CollectionCollection<?>

慕容森

原始类型和无界通配符之间的主要区别在于后者是类型安全的,也就是说,在编译级别,它检查集合中的项是否属于同一类型。编译器不允许您将字符串和整数添加到通配符类型的集合中,但它将允许您执行以下操作:<?>List&nbsp;raw&nbsp;=&nbsp;new&nbsp;ArrayList(); raw.add(""); raw.add(1);实际上,在无界通配符集合()的情况下,您根本无法向列表中添加任何内容,但是(来自Oracle文档):List<?> wildcard = new ArrayList<String>()null由于我们不知道c的元素类型代表什么,因此我们无法向其添加对象。add() 方法采用类型为 E 的参数,即集合的元素类型。当实际类型参数为 ?时,它代表某个未知类型。我们传递要添加的任何参数都必须是此未知类型的子类型。由于我们不知道那是什么类型,因此我们无法传递任何内容。唯一的例外是 null,它是每种类型的成员。

互换的青春

尖叫:Collection<?>请不要向我添加任何内容。我有一个严格的内容类型,...嗯,呃,我只是忘了它是什么类型。而 a 说:Collection这一切都很酷!你可以添加任何你喜欢的东西,我没有限制。那么,为什么编译器不应该转换为?因为它会带来很多限制。CollectionCollection<?>

繁华开满天机

一个我能想到的用例,为什么不被认为是假设我们有一个实例CollectionCollection<?>ArrayList现在,如果实例的类型为 or 或 ,则可以仅添加该类型(类型检查)。 不等效于 。ArrayList<Integer>ArrayList<Double>ArrayList<String>ArrayList<?>ArrayList<Object>但是只有 ,您可以添加任何类型的对象。这可能是编译器不考虑作为(类型检查)的原因之一。ArrayListArrayListArrayList<?>另一个原因可能是与没有泛型的Java版本向后兼容。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java