当前位置: 首页 > 知识库问答 >
问题:

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

洪光霁
2023-03-14

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

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

我知道什么

请有人用简单的话解释一下这件有趣的事是什么意思?不是关于


共有2个答案

梁丘烨
2023-03-14

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

T扩展类名

我将提供一个更有意义的例子,它可能会使我们更容易理解使用有界递归类型参数的概念。假设你有一个类Thingy。您希望Thingy的所有子类都具有可比性,但仅限于相同的子类。即你希望钉子能和钉子相提并论,但不是自行车:

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) { ... }
}

申颖逸
2023-03-14

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

我们有S成为类名

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

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

允许递归泛型类型定义。所以你可以像

ClassName<ClassName<ClassName<ClassName<?>>>> test;

不管值多少钱:)

编辑:给定

ClassName2<T extends ClassName<?>> extends ClassName<T>

相比之下,这相对容易。我们希望继承ClassName而不是“销毁”泛型参数,因此我们采用ClassName可以接受的一个参数,在本例中T扩展ClassName

此外,我们还有ClassName2

ClassName2<ClassName<ClassName<ClassName<?>>>> test2;
ClassName2<ClassName<ClassName2<ClassName<?>>>> test3;

然而,如果你愿意的话

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

(公共和abstrac修饰符并不真正影响这里的通用行为),你只能有这样的东西

ClassName3<ClassName3<ClassName3<ClassName3<?>>>> test4;
ClassName2<ClassName<ClassName3<ClassName3<?>>>> test5;

因为ClassNameClassName2不继承ClassName3

 类似资料:
  • 问题内容: 我以为Java擦除会在编译时消除泛型类型,但是当我自己对其进行测试时,我意识到在Bytecode中有一些有关泛型类型的信息。 这是我的测试: 我写了2节课: 和 我编译了两个类,并在通用类的某个地方看到了这一行 在非泛型类中: 所以很明显我在字节码中有通用信息,那么这个擦除的东西是什么? 问题答案: 一些通用类型信息存储在属性中。请参阅JLS 4.8 和4.6以及JVM规范4.3.4。

  • 问题内容: 我是从Joshua Bloch的google I / O困惑者演讲中得到的。这是代码 这个main方法会引发异常,因为它是原始类型,因此in中的所有泛型都将被删除,因此最终调用而不是。 我的问题是,即使我打电话是不是应该把它调用的方法,因为由于类型擦除,这种方法是有效的并且是类型的不是? 问题答案: 被调用的方法是在编译时定义的,而不是在运行时定义的。 如果在构造函数调用中添加参数,则

  • 我有一个返回泛型的函数: 所以,当我试图匹配一个函数结果时,我的问题是: 我得到一个警告:“类型模式数组[CustomerInfo到[CustomerApplication到]]中的非变量类型参数CustomerApplication-DDTO未选中,因为它已被擦除消除。” 这是否意味着在Array[]中可以得到任何类型的数组?所以我已经阅读了关于ClassTag和TypeTag的文章,但是误解了

  • 我有一个这样定义的方法: 我的单元测试我错误地这样测试它: 这应该会产生编译时错误(当我尝试使用javac编译它时,它会产生编译时错误),但eclipse允许它编译。 我真的不明白为什么eclipse允许这段代码编译,有人能提供一些信息吗,为什么这会在eclipse中编译? eclipse版本是:面向Web开发人员的eclipse Java EE IDE。版本:Luna Service Relea

  • 问题内容: 我正在为核心数据编写通用包装类。 这是我的一些基本类型。没什么特别的。 我已经将我的coredata写在协议中抽象化了。如果您让我知道您对我要提出的抽象的意见,我将不胜感激。但是在扩展中,我遇到了以下错误: 无法将类型“ NSFetchRequest”的值转换为预期的参数类型“ NSFetchRequest <_>” 不确定我该如何解决。我尝试了各种更改代码的尝试,但未成功…… 另外,

  • 问题内容: 类型擦除应该擦除所有泛型信息…如果是这种情况,那么像GSON这样的库如何使用泛型来确定反序列化为哪种类型? 例如 这将反序列 化为 将反序列化为 因此以某种方式在运行时使用通用信息。 问题答案: 类型擦除不会擦除所有类型信息。它不会从类,字段,返回类型和参数定义中将其删除。保留以下示例中的类型信息: 这是可以通过反射实现的。您可以检查给定的是否是该类,将其强制转换为该类并获取类型信息。