我在一个不相关的问题上看到了一些代码,但它让我很好奇,因为我从来没有看到过使用Java Generics这样的构造.创建一个可以作为类型参数本身或其自身后代的泛型类会有什么用处.这是一个例子:
abstract class A<E extends A<E>> {
abstract void foo(E x);
}
Run Code Online (Sandbox Code Playgroud)
我想到的第一件事就是将列表作为参数的列表.使用这段代码感觉很奇怪,你如何声明A类型的变量?递归声明!?
这甚至有用吗?如果是这样,你们中的任何人在代码中看到了吗?怎么用?
编辑
事实上,事实证明我的问题与这个只有不同的措辞相同,但这个问题的答案也将回答我的问题.
同样感谢参考奇怪的重复模板模式,该模式给出了一些历史背景和关于该主题的进一步解释.
这篇旧博客文章可能会给我们Java家伙提供最好的解释.
现在很难在这里选择一个正确的答案,因为它们都很有用,所以我会选择最终产生最多阅读材料的那个(上面引用)
如果没有这个,方法的参数foo就不能绑定到类型E.
如果您有B此抽象类的实现,则现在可以强制该方法foo还要求其参数为类型B.
class B extends A<B> {
void foo (B x){}
}
Run Code Online (Sandbox Code Playgroud)
没有它,foo就必须采取任何形式A.
我同意这个的语法不够优雅.
泛型不仅仅适用于列表等容器。这种“扩展自身”类型参数用于让超类在方法参数和返回类型等地方引用子类,即使在编译超类时没有实际的特定子类可用。它类似于C++ 中奇怪的重复模板模式。
您的示例的子类将声明为
class Foo extends A<Foo>
Run Code Online (Sandbox Code Playgroud)
继承的foo()方法就变成了
void foo(Foo x)
Run Code Online (Sandbox Code Playgroud)
看看如何A定义一个接受Foo参数的方法,即使它实际上并不知道Foo?
是的,这种事情很不寻常,但并非闻所未闻:内置的Enum类使用了类似的技巧。