"<? extends Object>"和"<E extends Object>"有什么区别?

17

<? extends Object><E extends Object>有什么区别?何时应该使用其中之一?


7
你可以重复使用 E - Sotirios Delimanolis
它们是互斥的。 - SLaks
在我的看法中,我会在静态实用方法中使用 <? extends AClassOrInterface> 来处理集合(set、list、map等)的元素,仅此而已。如果我想要字段(类型为 E 的字段或填充有类型为 E 的元素的集合)的类/接口定义,我会使用 <E extends MyClass> - Luiggi Mendoza
5个回答

16

这是我马上想到的一些不同之处:

  • Type parameter bounds can specify multiple bounds - T extends A & B, but with wildcard you cannot specify multiple bounds - ? extends A & B is invalid.

  • You can have lower bounds with wildcard - ? super A is valid, but not with the type parameter - T super A is not valid.

  • You cannot use wildcard bounds while creating a generic type. You have to use type parameter bounds.

  • Inside a method, if you want some relation between the type parameters of arguments passed, then you have to use type parameter bounds. For e.g, you want to pass two parameterized type with same type parameter. You can't do this with wildcard bounds. So the following method declaration will take two list of same type parameter, that extends Number.

    public <T extends Number> void merge(List<T> list1, List<T> list2) {
    }
    
最后,我会从《Effective Java - Item 28: 使用有界通配符增加API灵活性》中添加一些要点:
为了达到最大的灵活性,在表示生产者或消费者的输入参数上使用通配符类型。如果一个输入参数既是生产者又是消费者,则通配符类型对你没有好处:你需要精确的类型匹配,这就是你在没有任何通配符的情况下得到的。
不要将通配符类型用作返回类型。与其为用户提供额外的灵活性,不如强制他们在客户端代码中使用通配符类型。正确使用通配符类型,它们对于类的用户几乎是看不见的。它们导致方法接受应该接受的参数并拒绝应该拒绝的参数。如果类的用户必须考虑通配符类型,那么该类的API可能存在问题。

参考资料:


6
<? extends Object> 是一个有界通配符(扩展自Object的未知类型),而<E extends Object> 是类型受限的(E需要一个扩展Object的参数化类型)。
有界通配符与参数化上限之间最微妙的区别:
  • 创建泛型类时无法使用有界通配符,只允许使用带类型的参数。

  • 无法在需要向集合中添加项目的Collection中使用有界通配符,因为它是一个未知类型,集合不知道接收到的是什么类型,因此它不是类型安全的。

  • 无法将有界通配符绑定到多个泛型类型(边界)。

我希望这能帮助你。

<? extends Object><E extends Object>都是有界的,它们的上限是Object - Katona
实际上,在需要添加项目的集合中使用通配符是可以的,如果通配符是类型为 <? super SomeClass> 的话。 - Lorenzo Baracchi
@Lorenzo Baracchi,确实如此,但这并不是这里所问的问题。 :-) - Buhake Sindi
@BuhakeSindi 实际上,你的第二点在差异方面是错误的,因为没有任何差异,因此“类型绑定可以在需要向集合中添加项目的集合中使用...”能否解释一下? - manocha_ak
@manocha_ak,简单来说:创建一个简单的示例:Collection<? extend Object> collection = new ArrayList<? extends Object>();。现在,添加一个项目。如果您使用Eclipse IDE,您将看到它说,collection.add(null e)。这就是我的意思。?是一个通配符无界限制,这就是我在帖子中提到的。 - Buhake Sindi

5

如果您需要在后面引用该类型,请使用E。如果您不再需要引用该类型,请使用?


0
在泛型代码中,问号(?)被称为通配符,表示未知类型。通配符可用于各种情况:作为参数、字段或本地变量的类型;有时作为返回类型(虽然更好的编程实践是更具体)。通配符永远不会用作泛型方法调用、泛型类实例创建或超类型的类型参数。有关更多信息,请查看this

-1

<E> 声明了一个类型参数。
只有在创建泛型类型或方法时才能使用它。

<? ...> 是类型参数的通配符
只有在创建封闭泛型类型时才能使用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接