A <t extends =“”b =“”>和A <! - ?之间有什么区别?扩展B - >?</t>

时间:2011-03-06 15:56:42

标签: java generics

我是一名新的java学习者。最近我正在阅读Generic编程,让我对此感到困惑......

A<T extends B> and A<? extends B>

4 个答案:

答案 0 :(得分:18)

首先,这些是在不同环境中使用的完全不同的结构。

A<T extends B>是泛型类型声明的一部分,例如

public class A<T extends B> { ... }

它声明了类型参数为A的泛型类型T,并在T上引入了一个限制,因此T必须是B的子类型。


A<? extends B>是带有通配符的参数化类型,它可以在变量和方法声明等中用作普通类型:

A<? extends B> a = ...;

public void foo(A<? extends B> a) { ... }

A<? extends B> a之类的变量声明表示a的类型A参数化为B的某个子类型。

例如,鉴于此声明

List<? extends Number> l;
你可以:

  • List的某个子类型的Number分配给l

    l = new ArrayList<Integer>(); 
    
  • 从该列表中获取Number类型的对象:

    Number n = l.get(0);
    

但是,由于您不知道列表的实际类型参数,因此无法将任何内容放入列表l中:

Double d = ...;
l.add(d); // Won't compile

答案 1 :(得分:8)

?就是所谓的wildcard。它意味着任何扩展B的东西。

当您撰写List<T extends String>时,您的List只能包含T类型的元素。

当您撰写List<? extends String>时,您的List可以包含extends String

的任何元素

我希望我很清楚,因为这些概念很复杂。

答案 2 :(得分:5)

(长篇评论,不是答案)

完全不同的东西。语法的相似性是Java造成的严重错误。而这个错误导致了更大的错误 - 许多人试图将通配符理解为类型参数(即通配符捕获)

在Java发明它之前,没有A<? extends B>这样的东西。在那之前,研究人员使用的语法是A<B+>。 Java认为这对我们糟糕的程序员来说太神秘了,所以它发明了第一轮似乎读得更好的语法A<? extends B>

嗯,这是多么冗长和丑陋。如果API有一些通配符,它​​看起来像符号的呕吐物。

但最糟糕的是它引起的混乱。它看起来像一个类型参数。 Java是故意这样做的! Java并不相信它的程序员可以理解协变类型,所以语法上它使得可变类型看起来像参数化类型,引导程序员进入错误的理解方式,不可否认,这在某些场合很有用,但最终会让人无能为力

答案 3 :(得分:3)

泛型是一个复杂的主题,特别是在Java中。但基本上区别在于:

T延伸B

存在特定类型T,它仅限于B或B的子类,但它是特定的知识类型。任何普通的旧通用声明都是这样说的:<T extends Object>通过说T扩展B,我们说T比任何对象更有限,它必须特别是B的类型。 / p>

?延伸B

这意味着泛型类型是未知的,确切地说,但我们可以说它是扩展B.它可能是B,它可能是B的子类。带有通配符和单词extends,它意味着你可以从对象中获取B,但是你不能以类型安全的方式在对象中放置任何东西。 (?super B意味着相反 - 你可以把一些东西放在B的B或B的超类中,但你不能确定方法的返回值是什么。)