java - 解析 <T extends Interface<T>> 并结束潜在的无限循环

标签 java generics classloader javac

考虑一个以

开头的类定义

class Pokemon extends Playable<Pokemon>

这类似于更常见的 class Pokemon implements Comparable<Pokemon> ,这只是对 Pokemons 施加了总排序。

虽然我已经看到这个并写了一段时间,但我意识到(在回答一个问题之后)至少从理论的角度来看,如果不小心的话,解析中可能存在无限循环的风险。

考虑一下:
第 1 步:编译器或类加载器尝试解析(或加载)Pokemon , 但看到它需要解析 Playable<.>首先。
第 2 步:编译器然后意识到因为 PlayablePokemon 参数化, 它需要加载或解析 Pokemon .现在我们发现自己进入了第 1 步,并且建立了一个永无止境的循环。

在实践中,我们知道情况并非如此,因为它有效。那么循环是如何被打破的呢?我的理论是,在第 2 步结束时,编译器或类加载器只是停止并使用对 Pokemon 的“引用”,而不是提取 Pokemon 源代码。但我对 javac 了解不够或 Classloaders来确认这一点。有人可以权衡一下吗?

最佳答案

这类似于此声明中的“循环”:

class LinkedListNode {
    private String data;
    private LinkedListNode next;
    ...
}

为了处理 private LinkedListNode next 字段,编译器只需要知道 LinkedListNode 是一个类型。此时它不需要有一个完整的类型,因为类型名称提供了足够的信息来声明该字段。

类似地,当您声明一个引用其自身类型作为其继承结构的一部分的泛型类时,编译器不需要完整的类型来完成对声明的解析。

关于java - 解析 <T extends Interface<T>> 并结束潜在的无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45751264/

相关文章:

java - 如何返回 <T extends Comparable< 的通用数组? Java 中的 super T>>?

java - 保存数据时卡住gui jdbc,为什么?

java - 初始化错误无法在 Gradle 构建中调用合约测试

java - 循环遍历所有组合

C# 存储库实现,需要有关通用修复的建议

generics - F# 中泛型类型的泛型算术运算

Java 类加载器独立于 jar 文件的系统类加载器

java - Selenium Wire 日志为空

java - 使用 ClassLoader.getResource() 加载 BufferedImage

java - 如何在没有 box2d libgdx 的情况下对对象施加脉冲