通过类型擦除理解java递归泛型类型定义

通过类型擦除理解java递归泛型类型定义,java,generics,inheritance,Java,Generics,Inheritance,面对这一行代码,我感到非常困惑: public abstract class ClassName<T extends ClassName<?>>{} public抽象类ClassNamepublic表示该类对所有其他类可见 abstract表示不能实例化该类(您必须为此找到一个非抽象子类) 继承是面向对象编程中的一个重要概念。阅读一本关于OOP的书或查阅维基百科 T扩展ClassName意味着类型参数T上有一个上限,因此T需要是ClassName的子类?表示无界类型参数

面对这一行代码,我感到非常困惑:

public abstract class ClassName<T extends ClassName<?>>{}

public抽象类ClassName
public
表示该类对所有其他类可见
abstract
表示不能实例化该类(您必须为此找到一个非抽象子类)
继承是面向对象编程中的一个重要概念。阅读一本关于OOP的书或查阅维基百科

T扩展ClassName
意味着类型参数
T
上有一个上限,因此
T
需要是
ClassName
的子类<代码>?
表示无界类型参数

我将提供一个更有意义的示例,使您更容易理解使用有界递归类型参数的概念。假设您有一个类
Thingy
。您希望
Thingy
的所有子类都具有可比性,但仅限于相同的子类。Ie您希望钉子可以与钉子相媲美,但不能与自行车相媲美:

interface Thingy<T extends Thingy<T>> extends Comparable<T> {}

class Nail implements Thingy<Nail> {
    @Override public int compareTo(Nail o) { ... }
}

class Bike implements Thingy<Bike> {
    @Override public int compareTo(Bike o) { ... }
}
interface Thingy扩展了{}
类钉子实现的东西{
@重写公共整数比较(Nail o){…}
}
类自行车工具{
@重写公共整数比较(Bike o){…}
}

因此
ClassName
有一个通用参数
T
,该参数需要满足特定的要求,在这种情况下扩展了特定类型
S
,这意味着
T
必须继承
S
。现在这个例子中有趣的事情是这个
S

我们有
S
成为
ClassName
,因此
T
必须使用通配符从
ClassName
继承。对于通配符又名问号,请查看Michael Markidis在对您的问题的评论中给出的链接

现在真正有趣的是这个定义

public abstract class ClassName<T extends ClassName<?>>
然而,如果你愿意的话

class ClassName3<T extends ClassName3<?>> extends ClassName<T>

class classname3令人困惑的是,抽象类怎么可能是继承自它的类的类型?这听起来像是无休止的故事。你只需要看看一个子类的样子
class Foo扩展类名{}
class Bar扩展类名{}
可能是两个这样的子类…@Evgeny Mishustin通过类型擦除工作,这是泛型的重要概念。是的,无休止的故事很酷,看我的答案。以前甚至不知道这种可能性:-Dwent学习“类型擦除”我的讲师错过了那部分]@GreenThor:类型擦除与此毫无关系。哦,我害怕听到“递归”实际上,下一个类我有一个公共抽象类ClassName2@EvgeniyMishustin根据您的评论扩展了我的答案:-)我很高兴类型擦除提示可以帮助您
ClassName2<T extends ClassName<?>> extends ClassName<T>
ClassName2<ClassName<ClassName<ClassName<?>>>> test2;
ClassName2<ClassName<ClassName2<ClassName<?>>>> test3;
class ClassName3<T extends ClassName3<?>> extends ClassName<T>
ClassName3<ClassName3<ClassName3<ClassName3<?>>>> test4;
ClassName2<ClassName<ClassName3<ClassName3<?>>>> test5;