Java泛型与有界通配符

3
什么是类声明的不同之处?
public abstract class Super1<T extends Super1<T>> {...}  

并且

public abstract class Super2<T extends Super2<? super T>> {...}

使用第一种方法,我能够创建子类(类似于Java中的Enum类型)。
public class Sub1 extends Super1<Sub1> {...}

但是我想知道是否可以像第2个示例那样声明超类。它有任何意义吗?但是我无法创建子类,例如:

public class Sub2 extends Super2<Object> {...}

我认为对象可以作为T的超类型?还有另一种形式,我可以想到的是:
public abstract class Super3<T extends Super3<? extends T>>

我正在尝试学习泛型,非常感谢您的帮助。


1
你不能使用 Super2<Object>,因为 Object 没有 extends Super2<Object> - Sebastian
@JKV:它是有效的,但并不实用。请给我展示一个它能工作而“class Super1<T>”不能的案例。 - newacct
@newacct,我认为这个链接可以帮助你 http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ206 - JKV
@newacct,如果从讨论中得出结论认为自引用泛型类型没有用处,那么我开始怀疑为什么它被允许作为语言结构的一部分? - JKV
@newacct,我正在学习Java中的泛型,对类型有了更深入的了解。即使我发现自引用类型在类层次结构具有多级继承时可能会失败,从而使它们无法用于流畅的接口设计。在您虚构的示例中,我认为如果有另一个子类型Node<T>从第二级继承的结点中扩展,那么它可能不起作用。就像A<-B<-C,假设A是基本节点类型,B扩展A,C扩展B,我们可以说C也是A的子类型,但<T extends A<T>>,我可以创建B为B extends A<B>,但我无法以类似的方式从B创建C。 - JKV
显示剩余5条评论
1个回答

6

当处理具有继承的自我引用泛型类型时,这些声明常常会出现。关键字是-自我引用继承

让我们通过一个例子来理解这个概念。假设我们有一个实现了Comparable<Car>的类Car,以及Car的子类-Mercedes

class Car implements Comparable<Car> { ... }
class Mercedes extends Car { }

现在,您也希望Mercedes是可比较的,因此您可能会想让我们在那里实现一个Comparable<Mercedes>,然后执行以下操作:

class Mercedes extends Car implements Comparable<Mercedes> { }

...这就是你遇到错误的地方。问题在于,现在Mercedes类同时实现了Comparable<Car>Comparable<Mercedes>,这是不允许的。

更多阅读:

因此,您需要从中移除Comparable<Mercedes>。现在,您只需将Mercedes类实现Comparable<Car>

然后,您可以创建一个使用自引用类型参数的类,如下所示:

class Garage<T extends Comparable<T>> { }

当创建一个同时包含 CarMercedes 的实例时,您可以按照以下方式进行:

Garage<Car> carComp = new Garage<Car>();
Garage<Mercedes> mercedesComp = new Garage<Mercedes>();

你能发现错误吗?是的,在第二个声明中有一个错误。不能使用Mercedes类型参数,因为它不满足T extends Comparable<T>的限制条件。由于Mercedes实现了Comparable<Car>,所以现在该怎么办呢?

这就是那个声明的用处。让我们将你的类Garage改成这样:

class Garage<T extends Comparable<? super T>> { }

..然后你的两个实例化将会成功,因为现在Mercedes符合限制条件。


感谢您的解释。我还有一个问题。我可以声明一个类似于public abstract class Super2<T extends Super2<? super T>> {...}的东西吗?请注意,Super2被使用了两次(T extends Super2<? super T>)。如果这是一个有效的声明,那么可能的子类是什么!非常感谢您的回答。 - JKV
@JKV 是的,你可以有这样的声明。实际上,这就是真正的自引用泛型类型。 - Rohit Jain
尝试使用class Sub extends Super<Sub> - Rohit Jain
是的,没错!如果我的Super2被定义为class Super2<T extends Super2<T>>(我认为基于Enum类型的类就是这样定义的),那么class Sub extends Super2<Sub>仍然有效,但是我有一个有界通配符<T extends Super2<? super T>>,而不仅仅是<T extends Super2<T>>。有界通配符允许我创建与没有有界通配符相同的子类。我尝试了不同的组合,但是我无法找到一个正确的有界通配符的子类,它们是不同的。谢谢回复。 - JKV

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