Java Generic bound (constraint) for Enum
Asked Answered
S

1

6

I'm trying to bound (constrain) a Java generic type variable to be an enum (any enum) and failing. Might you be able to tell me why?

import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.cellprocessor.ift.StringCellProcessor;

public class ParseEnum<TEnum extends Enum> extends CellProcessorAdaptor implements StringCellProcessor {

    public Object execute(final Object value, final CsvContext context) {
        ...
        final TEnum result;
        if (value instanceof TEnum) {
            result = (TEnum) value;
        } else if( value instanceof String ) {
                result = TEnum.valueOf((String)value);
        } else {
            ...
        }
        ...
}

(These are bits of my actual code attempting to extend a SuperCSV CellProcessor. )

value instanceof TEnum gives me this error (in Eclipse):

"Cannot perform instanceof check against type parameter TEnum. Use its erasure Enum instead since further generic type information will be erased at runtime"

TEnum.valueOf((String)value) gives me this error:

"The method valueOf(Class, String) in the type Enum is not applicable for the arguments (String)"

Soble answered 11/2, 2013 at 14:26 Comment(1)
The second issue is easy enough: the Enum.valueOf method takes two arguments!Fries
S
8

You'll have to pass the enum class to do that (just like EnumSet.allOf() does).

public class ParseEnum<TEnum extends Enum<TEnum>> extends CellProcessorAdaptor implements StringCellProcessor {

    private Class<TEnum> enumType;

    public ParseEnum(Class<TEnum> enumType) {
        this.enumType = enumType;
    }

    public Object execute(final Object value, final CsvContext context) {
        ...
        final TEnum result;
        if (value.getClass().equals(enumType)) {
            result = (TEnum) value;
        } 
        else if (value instanceof String) {
            result = Enum.valueOf(enumType, (String) value);
        } 
        else {
            ...
        }
Satyr answered 11/2, 2013 at 14:35 Comment(4)
Thanks! But this would break the contract with SuperCSV, I believe. Why can't I use TEnum.class inside execute?Soble
Because, as the error message indicates, Java uses erasure. The generic type is only checked at compile time. At runtime, the actual concrete type of the generic parameter (TEnum) is unknown. All the JVM knows is that it is an instance of Enum.Satyr
Thanks again JB Nizet. Might I dare ask - why? Why is the concrete type unknown at runtime?Soble
Because Java doesn't have true, reified generics. The type safety is only checked at compile time, and the generic types are "erased" by the compiler. See docs.oracle.com/javase/tutorial/java/generics/erasure.htmlSatyr

© 2022 - 2024 — McMap. All rights reserved.