我猜您正在谈论在类型参数声明中使用扩展。在这种情况下:
class My_Abstract<T extends SomeAbstract>
有一个称为有界类型参数T
那一定是SomeAbstract
或其某些子类型。
class My_Abstract<SomeAbstract>
有一个名为的无界类型参数SomeAbstract
那可以是任何东西。注意SomeAbstract
不再指实际类型SomeAbstract
第一个例子就使用了这个!
扩展一下:想象一下如果第二个声明是class My_Abstract<T>
. The T
显然有一个类型参数,而不是实际类型。但它不必被称为T
...它可以被称为E
or Bob
or SomeAbstract
。在所有这些情况下,它仍然只是一个类型参数......实际类型永远不会去那里,也没有任何意义(类型参数的全部要点是不引用特定类型,而是引用特定类型)相反,当创建类的实例时,允许将其他类型放在其位置)。
在您编辑的代码中,更改My_Child
的声明
class My_Child extends My_Abstract<Object>
你会看到差异。如果您实际上尝试使用类型参数执行某些操作SomeAbstract
在第二个版本中,您还会发现无法调用真实中声明的任何方法SomeAbstract
班级。这是一个很好的例子,说明为什么您应该始终遵循使用单字母类型参数的约定......如果您不这样做,那真的很令人困惑。
这真的很长,但我还想指出,所有这些基本上与你问题的前半部分无关。通配符如? extends SomeAbstract
and ? super SomeAbstract
不用于类型参数声明(例如定义泛型类时使用的声明),它们主要用于方法参数。List
是解释为什么需要通配符的典型示例,因为它作为对象容器的性质使其相对容易理解,但与它们相关的规则适用于任何泛型类型。我试图用相对笼统的术语来解释这一点这个答案 https://stackoverflow.com/questions/2248390/java-generics-collections-max-signature-and-comparator/2248503#2248503.