在泛型中接受自身作为类型参数有什么用

2022-09-04 21:31:30

我看到了一些关于一个不相关的问题的代码,但它让我感到好奇,因为我从未见过Java泛型的这种结构。创建一个泛型类有什么用,它可以作为类型参数本身或自身的后代。下面是示例:

abstract class A<E extends A<E>> {
    abstract void foo(E x);
}

首先想到的是一个以列表为参数的列表。使用这段代码感觉很奇怪,你如何声明A类型的变量?递归声明!?

这甚至有效吗?如果是这样,你们中是否有人在代码中看到过?它是如何被使用的?


编辑

事实上,事实证明我的问题与这个问题相同,只是措辞不同,但这个问题的答案也会回答我的问题。

也感谢您对奇怪的重复模板模式的引用,该模式提供了一些历史背景和有关该主题的进一步解释。

这个旧的博客文章可能给出了我为我们Java人找到的最好的解释。

现在很难在这里选择一个正确的答案,因为它们都是有帮助的,所以我会选择最终产生最多阅读材料的答案(上面引用)


答案 1

否则,方法的参数无法绑定到类型 。fooE

如果您有此抽象类的实现,则现在可以强制该方法还要求其参数的类型为 。BfooB

 class B extends A<B> {
      void foo (B x){}
 }

没有它,将不得不采取任何类型的.fooA

我同意这个语法不那么优雅。


答案 2

泛型不仅适用于列表等容器。这种“扩展自身”类型参数用于让超类在方法参数和返回类型等位置引用子类,即使编译超类时没有实际的特定子类可用。它类似于C++中奇怪的重复模板模式

示例的子类将声明为

class Foo extends A<Foo>

并且继承的方法变为foo()

void foo(Foo x)

了解如何定义一个采用参数的方法,即使它实际上并不知道?AFooFoo

是的,这种事情很不寻常,但并非闻所未闻:内置的Enum类使用类似的技巧。


推荐