代码
Set<? extends MyClass> mySet = new HashSet<>();
mySet.add(new MyClass());
会产生错误消息。原因是编译器不知道 mySet的类型。它只知道 mySet 的类型是 Set&lt; SomeType&gt; 其中 SomeType 是 MyType的子类型。由于编译器不知道哪个类型 Set&lt;? extends MyClass&gt; 指的是它允许插入的唯一内容该类型 null。
由于这非常令人困惑,并且因为对于唯一可能元素为 null 的集合的使用最少,所以不允许使用&lt;?在声明对象时扩展 SomeClass&gt; ,即如上例所示。此表单应仅使用 来声明将在以后具体化的抽象(例如参数或泛型类或方法)。
我意识到这不是一个问题,但我想知道这个想法的反应是什么。
答案 0 :(得分:4)
我不确定是否买了它。我可以想象
的情况Set<? extends MyClass> mySet = getOtherSet();
其中getOtherSet
的返回类型可能是Set<MySubClass>
,甚至是Set<? extends MyClass>
。这是,也应该是合法使用泛型。
区分上述合法使用与您描述的有问题的案例的唯一方法正是Java已经做的 - 它在编译时产生错误消息。
答案 1 :(得分:0)
Set<? extends MyClass>
一般来说是非常有用的类型。您可以使用Set<? extends MyClass>
方法参数,该参数允许您使用Set<OneClass>
或Set<AnotherClass>
来调用它。如果所有方法都需要从中获取MyClass
元素,那就没问题了。或者,你可以有一个像
Set<? extends MyClass> mySet = someObject.someMethod();
该方法可以返回不同类型的集合(某些实例可能返回Set<OneClass>
,而其他实例可能会返回Set<AnotherClass>
),现在您只需要获取MyClass
事情就这样了。
您要展示的示例专门处理使用新的空集初始化Set<? extends MyClass>
。我同意这个案子没那么有用。但是,如果我们需要制定一个规则来禁止这种情况,那么它必须分配一个对象创建表达式,而不是分配其他表达式(如方法调用),即使它们是等价的(方法调用也可能只是返回一个新的空集)。我认为,如果没有造成任何伤害,明确排除这种情况是不合理的。您可以同样认为能够创建长度为0的数组是一个相当无用的,应该是不允许的;但是,它使语言更加通用,能够处理边缘情况。