我是一名新的java学习者.最近我正在阅读Generic编程,让我对此感到困惑......
A<T extends B> and A<? extends B>
Run Code Online (Sandbox Code Playgroud)
    axt*_*avt 18
首先,这些是在不同环境中使用的完全不同的结构.
A<T extends B> 是泛型类型声明的一部分,如
public class A<T extends B> { ... }
Run Code Online (Sandbox Code Playgroud)
它声明了A带有类型参数的泛型类型T,并引入了一个绑定T,因此它T必须是一个子类型B.
A<? extends B> 是带有通配符的参数化类型,它可以在变量和方法声明等中使用,作为普通类型:
A<? extends B> a = ...;
public void foo(A<? extends B> a) { ... }
Run Code Online (Sandbox Code Playgroud)
变量声明如A<? extends B> a指型的a是A与一些亚型参数B.
例如,鉴于此声明
List<? extends Number> l;
Run Code Online (Sandbox Code Playgroud)
您可以:
将List某个子类型分配Number给l:
l = new ArrayList<Integer>(); 
Run Code Online (Sandbox Code Playgroud)Number从该列表中获取类型的对象:
Number n = l.get(0);
Run Code Online (Sandbox Code Playgroud)但是,您不能将任何内容放入列表中,l因为您不知道列表的实际类型参数:
Double d = ...;
l.add(d); // Won't compile
Run Code Online (Sandbox Code Playgroud)
        一般而言,泛型是一个复杂的主题,尤其是在 Java 中。但基本上区别在于:
有一个特定的类型 T,它只限于是 B 或 B 的子类,但它是一个特定的已知类型。任何简单的旧泛型声明就像在说:<T extends Object>通过说 T 扩展 B,我们是说 T 比任何对象都更受限制,它必须特别是 B 的一种类型。
这意味着泛型类型是未知的,确切地说,但我们可以说它扩展了 B。它可能是 B,它可能是 B 的子类。使用通配符和字扩展,这意味着你可以从对象中取出 B,但不能以类型安全的方式在对象中放入任何东西。(?super B 的意思正好相反——你可以把一些东西放在一个 B 或 B 的超类的方法参数中,但你不能确定一个方法的返回值是什么。)
(长评,不是答案)
完全不同的东西.语法的相似性是Java造成的严重错误.而这个错误会导致更大的错误 - 许多人试图将通配符理解为类型参数(即通配符捕获)
A<? extends B>直到Java发明它之前没有这样的事情.在此之前,研究人员使用的语法是A<B+>.Java认为这对我们糟糕的程序员来说太神秘了,所以它发明了A<? extends B>第一轮看起来更好看的语法.
嗯,这是多么冗长和丑陋.如果API有一些通配符,它看起来像符号的呕吐物.
但最糟糕的是它引起的混乱.它看起来像一个类型参数.Java是故意这样做的!Java并不相信它的程序员可以理解协变类型,所以语法上它使得可变类型看起来像参数化类型,引导程序员进入错误的理解方式,不可否认,这在某些场合很有用,但最终会让人无能为力.