如何将 sealed 类 与泛型一起使用?

How to use sealed classes with generics?

我有一个 parent 抽象 class 和 child class es,它们采用泛型。

public abstract sealed class Parent<T> permits ChildA, ChildB {}

public non-sealed class ChildA<T extends FileTypeA> extends Parent{}

public non-sealed class ChildB<T extends FileTypeB> extends Parent{}

在 parent class 中,我收到警告:

ChildA is a raw type. References to generic type ChildA<T> 
       should be parameterized

ChildB is a raw type. References to generic type ChildB<T> 
       should be parameterized

在 child classes 中,我收到警告:

Parent is a raw type. References to generic type Parent<T> 
       should be parameterized

像这样对它们进行参数化:

public abstract sealed class Parent<T> 
    permits ChildA<T extends FileTypeA>, ChildB<T extends FileTypeB> {}

甚至

public abstract sealed class Parent<T> 
    permits ChildA<T>, ChildB<T> {}

报错:

Bound mismatch: The type T is not a valid substitute for the 
    bounded parameter <T extends FileTypeA> of the type ChildA<T>

如何删除这些警告和错误?

警告“Parent is a raw type”与密封的 classes 完全无关,因为在 Parent<T> 是时使用 extends Parent由于存在泛型,泛型 class 将导致此类警告。

您很可能想使用

public non-sealed class ChildA<T extends FileTypeA> extends Parent<T> {}

public non-sealed class ChildB<T extends FileTypeB> extends Parent<T> {}

另一个问题似乎是 Eclipse 错误,因为我只能在那里重现警告。当我将声明更改为 permits ChildA<?>, ChildB<?> 时,警告消失了,但是您 不应该 这样做。

Java Language Specificationpermits 子句定义为

ClassPermits:
    permits TypeName {, TypeName}

TypeName is linked to

TypeName:
    TypeIdentifier
    PackageOrTypeName . TypeIdentifier

PackageOrTypeName:
    Identifier
    PackageOrTypeName . Identifier

这显然会导致一系列没有任何类型参数的点分隔标识符。一贯地,javac 拒绝像 permits ChildA<?>, ChildB<?>.

这样的结构

换句话说,Eclipse 不应在此处生成警告,更重要的是,不应在 permit 子句中接受参数化类型。您最好的选择是等待修复 Eclipse 的 Java 17 支持。您可以在整个 Parent class 中添加一个 @SuppressWarnings("rawtypes") 以使警告消失,但由于这会影响整个 class,因此我不推荐这样做。