
本文旨在解决 java 密封类 (sealed class) `permits` 子句中涉及泛型类型参数导致的编译错误。核心问题在于 `permits` 子句要求列出的是类型名称 (typename),而非包含泛型参数的类类型 (classtype)。文章将详细解释这一规范,提供正确的代码示例,并阐述不同 java 编译器 (如 `javac` 和 `ecj`) 在处理此语法时的差异,帮助开发者避免和解决相关编译问题。
Java 17 引入的密封类(Sealed Class)特性允许开发者对类的继承或接口的实现进行更严格的控制。通过 sealed 关键字,一个类或接口可以声明其允许被哪些特定的子类或实现类继承或实现。这些被允许的子类或实现类必须在 permits 子句中明确列出。
permits 子句的语法旨在提供一个清晰的、可枚举的列表,表明哪些类型是密封类或接口的直接已知子类。然而,在使用泛型时,开发者可能会遇到一个常见的编译陷阱。
当密封类本身是泛型类,并且其允许的子类也是泛型时,直观上可能会认为需要在 permits 子句中包含泛型类型参数。例如,考虑以下结构:
public sealed abstract class APath<R> permits APath<R>.LastWildcard<R>, APath<R>.WholeWildcard<R> {
protected final List<ADir> dirs;
public final class LastWildcard<R1> extends APath<R1> {
// ...
}
public final class WholeWildcard<R1> extends APath<R1> {
// ...
}
}
public sealed abstract class ADir permits ADir.Wildcard, ADir.Dir {
public final class Wildcard extends ADir {}
public final class Dir extends ADir {}
}在这种情况下,Maven 使用 javac 编译器进行编译时,会报告一系列错误,其中第一个错误通常指向 permits 子句中泛型类型参数的位置,例如:
立即学习“Java免费学习笔记(深入)”;
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[13,52] '{' expected
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[15,25] class, interface, enum, or record expected这些错误信息看起来可能令人困惑,但其根本原因在于 permits 子句对泛型参数的语法要求与 extends 或 implements 子句不同。
根据 Java 语言规范(JLS),permits 子句中列出的是类型名称 (TypeName),而不是类类型 (ClassType)。这意味着在 permits 子句中,我们应该只使用类的简单名称或完全限定名,而不应包含任何泛型类型参数。
因此,即使 APath 及其子类 LastWildcard 和 WholeWildcard 都是泛型类型,在 permits 子句中也必须省略泛型参数。
正确的代码示例:
public sealed abstract class APath<R> permits APath.LastWildcard, APath.WholeWildcard {
protected final List<ADir> dirs;
public final class LastWildcard<R1> extends APath<R1> {
// ...
}
public final class WholeWildcard<R1> extends APath<R1> {
// ...
}
}通过移除 permits 子句中的泛型类型参数 (<R> 和 <R1>),代码将符合 Java 语言规范,并能顺利通过 javac 编译。
在开发过程中,您可能会发现某些集成开发环境(IDE),如 Eclipse 或基于 Eclipse LSP 的 VSCode Java 插件,并不会立即报告上述错误。这通常是因为这些 IDE 使用了不同的 Java 编译器。
这种编译器行为上的差异解释了为什么在 IDE 中代码看起来没有问题,但在使用 Maven 构建时却出现编译错误。因此,始终以 javac 的行为为准,并确保代码严格符合 Java 语言规范,是保证项目可移植性和正确性的最佳实践。
通过理解 permits 子句的精确语法要求以及不同编译器之间的潜在差异,开发者可以更有效地使用 Java 密封类,避免常见的编译错误,并构建出健壮、符合规范的 Java 应用程序。
以上就是解决 Java 密封类 permits 子句中的泛型编译问题的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号