Categories
discuss

How to use sealed classes with generics?

I have a parent abstract class and child classes which take generics.

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

In the parent class, I am getting warnings:

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

In the child classes, I am getting warnings:

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

Making them parameterized like this:

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

Or even

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

Gives the error:

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

How to remove these warnings and errors?

Answer

The warning “Parent is a raw type” is entirely unrelated to sealed classes, as using extends Parent when Parent<T> is a generic class will cause such a warning since Generics exist.

You most probably want to use

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

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

The other issue seems to be an Eclipse bug, as I can only reproduce the warning there. When I change the declaration to permits ChildA<?>, ChildB<?>, the warning disappears, but you should not do this.

The Java Language Specification defines the permits clause as

ClassPermits:
    permits TypeName {, TypeName}

whereas TypeName is linked to

TypeName:
    TypeIdentifier
    PackageOrTypeName . TypeIdentifier

PackageOrTypeName:
    Identifier
    PackageOrTypeName . Identifier

This clearly leads to a sequence of dot separated identifiers without any type parameters. Consistently, javac rejects a construct like permits ChildA<?>, ChildB<?>.

In other words, Eclipse should not generate a warning here and even more importantly, not accept parameterized types in a permit clause. Your best option is to wait for a fix of Eclipse’s Java 17 support. You could add a @SuppressWarnings("rawtypes") to the entire Parent class to make the warning go away, but since that would affect the entire class, I do not recommend it.

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..