【问题标题】:Understanding Java bound generic type within collection [duplicate]了解集合中的 Java 绑定泛型类型
【发布时间】:2016-07-24 13:06:56
【问题描述】:

我有一个通用绑定类型的集合,定义如下:

Set<? extends BasicShape> shapes = new HashSet<>();

在我的实现中(为了这个问题),BasicShape 不是抽象的。

我希望那时能够做到:

shapes.add(new BasicShape())

但我不能,因为编译错误而失败:

I have verified,并且 extends 是包容性的 - 这意味着它包括上限本身(在我的情况下 - BasicShape)。

我在其他 SO 线程中找不到此特定问题的答案。

有人可以解释一下这种行为吗?

【问题讨论】:

  • Set&lt;T extends BasicShape&gt; shapes = new HashSet&lt;&gt;(); 无法编译。请发帖minimal reproducible example
  • 为什么不设置? (另外,Tunaki 说过的话。)
  • 你的意思是Set&lt;? extends BasicShape&gt;
  • @OliverCharlesworth:这是我即将讲授的一门课程的理论问题。从技术上讲,对于我的具体用法,我可以省略边界,但这种情况在现实中可能以一种或另一种方式发生,我想完全理解它们。
  • 你应该使用 super BasicShape> 以添加 BasicShape,而 以便对其进行迭代

标签: java generics


【解决方案1】:

当您将shapes 声明为时

Set<? extends BasicShape> shapes = new HashSet<>();

这意味着您可以将Set&lt;BasicShape&gt;Set&lt;Rectangle&gt;Set&lt;Circle&gt; 等分配给该变量...

因此,您不能将任何BasicShape 添加到shapes,因为(据编译器所知)您可能正在尝试将Circle 添加到Set&lt;Rectangle&gt;

如果您将声明更改为:

Set<BasicShape> shapes = new HashSet<>();

您可以将任何BasicShape 实例添加到该Set

【讨论】:

  • 编译器无法判断我是否也将 Circle 添加到 Set 中。为什么只有在尝试添加新的 BasicShape 而不是添加新的 Circle 时才会失败?如果这只是分配问题 - 如果我真的会做分配,我不会得到一个未经检查的分配吗?因为现在我没有分配任何东西,只是试图用项目填充集合......此外,如果我实际上不能包含它的类型,那么说明扩展的意义是什么?
  • @aviadcohen 在您的示例中shape 的编译时类型是BasicShape,但它的运行时类型可以是Circle。由于泛型仅在编译时适用(在它们泛型类型参数被编译器擦除之前),编译器不允许将shape 添加到shapes。如果您尝试将Circle 添加到Set&lt;Rectangle&gt;,编译器也会给您一个错误。
  • @aviadcohen 当你有一个Collection&lt;? extends BaseType&gt; 变量时,你不能向它添加任何东西,因为你不知道这个 Collection 可以包含哪个 BaseType 的子类型。您只能从 Collection 中获取元素并确保它们都是 BaseType 的实例。这是 PECS 术语(Producer Extends Consumer Super)的一部分——在本例中——Collection&lt;? extends BaseType&gt; 可以生成 BaseType 的实例,但不能使用它们。
  • 我想我终于明白了(使用你的答案+观察@Tunaki 引用的类似线程)。
猜你喜欢
  • 1970-01-01
  • 2017-12-24
  • 1970-01-01
  • 1970-01-01
  • 2021-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-19
相关资源
最近更新 更多