使用与SomeAbstract
我正在从DotNet转向java,这种扩展的想法是新的。
我看过一些post,完全解释使用List
List
vs. List
List
vs. List
,但我猜测在generics中使用和不使用扩展之间没有区别。
真的吗? 如果使用抽象类作为父级,答案会改变吗?
class My_AbstractExtends
与
class My_Abstract
编辑
按如下方式创建子类
class My_ChildExtends extends My_AbstractExtends
与
class My_Child extends My_Abstract
我猜你在谈论在类型参数声明中使用extends。 在这种情况下:
class My_Abstract
有一个名为T
的有界类型参数,必须是SomeAbstract
或它的某个子类型。
class My_Abstract
有一个名为SomeAbstract
的无界类型参数可以是任何东西。 请注意, SomeAbstract
不再引用第一个示例使用的实际类型SomeAbstract
!
为了扩展:假设第二个声明是class My_Abstract
。 T
显然有一个类型参数,而不是实际类型。 但它不必被称为T
……它可以被称为E
或Bob
或SomeAbstract
。 在所有这些情况下,它仍然只是一个类型参数…实际类型永远不会去那里,它也没有任何意义(类型参数的整点是不引用特定类型,但而是在创建类的实例时允许其他类型放在其位置)。
在您编辑的代码中,将My_Child
的声明更改为
class My_Child extends My_Abstract
你会看到差异。 如果你真的试图在第二个版本中使用类型参数SomeAbstract
,你也会发现你不能调用在真正的SomeAbstract
类中声明的任何方法。 这就是为什么你应该总是遵循使用单字母类型参数的惯例的一个很好的例子…如果你不这样做,那真是令人困惑。
这个问题变得非常漫长,但我还要注意,所有这些与你问题的前半部分基本无关。 通配符喜欢? extends SomeAbstract
? extends SomeAbstract
和? super SomeAbstract
? super SomeAbstract
不用于类型参数声明(例如定义generics类时使用的那些),它们主要用于方法参数。 List
是一个典型的例子,用于解释为什么需要通配符,因为它作为对象容器的性质使它相对容易理解,但与它们相关的规则适用于任何generics类型。 我试着在这个答案中以相对笼统的方式解释这一点 。
它可以让你在其他地方引用T
public class A{ public A(T x){this.x=x;} public T x; }
然后,您的类的用户可以使用其原始类型,而不必使用SomeClass。
MyObject x = new A(new MyObject()).x;
在generics类声明中使用extends
:
- 将可用作参数的类型限制为从扩展类下降的类型。
- 允许generics类调用扩展类中声明的方法。
‘?’ 当手头的代码不关心类型参数的特定类型时,关键字用在方法中,但只关心它上面的低(扩展)或上(超)绑定。
维基百科以非常务实的方式解释了不同结构的净效应。
要理解为什么需要几种不同的结构来指定generics,你必须阅读协方差和逆变 ,这是在generics存在的情况下静态类型安全规则的理论名称。