设置<! - 扩展MyClass - >应该被禁止作为对象声明

时间:2012-04-21 23:33:53

标签: java generics extends

代码

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; ,即如上例所示。此表单应仅使用 来声明将在以后具体化的抽象(例如参数或泛型类或方法)。

我意识到这不是一个问题,但我想知道这个想法的反应是什么。

2 个答案:

答案 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的数组是一个相当无用的,应该是不允许的;但是,它使语言更加通用,能够处理边缘情况。