Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum with generic base class passed as contructor parameter

Tags:

java

generics

I'm attempting to create an enum whose constructor accepts an object whose base class is a generic class.

I seem to be unable to fetch the underlying generic type from within the enum however, Object gets returned instead of T.

Is there a way to do this?

abstract public class Field<T> {
    abstract public T get();
}

public class IntegerField extends Field<Integer> {
    public Integer get() {
        return 5;
    }
}

public class StringField extends Field<String> {
    public String get() {
        return "5";
    }
}

public enum Fields {
    INTEGER (new IntegerField()),
    STRING  (new StringField());

    private final Field<?> field; // <<--- I can't have Field<T>, enum's can't be generic. :( 

    <T> Fields(Field<T> field) {
        this.field = field;
    }

    public <T> T get() {
        return field.get(); // <<--- Returns Object, not T
    }
}
like image 789
Ian Avatar asked Aug 08 '26 01:08

Ian


2 Answers

The issue is that enums can't be generically typed so even if you cast that get call ((T) field.get()) you won't have type safety because it will agree with any assignment (you could compile this successfully for instance: boolean b = Fields.INTEGER.get()).

Just use constants instead:

public final class Fields {
   public static final Field<Integer> INTEGER = new IntegerField();
   public static final Field<String> STRING = new StringField();
}
like image 127
Dave Moten Avatar answered Aug 09 '26 15:08

Dave Moten


Why do you think an enum is preferable to this?

public final class Fields {
    public static final Field<Integer> INTEGER = new IntegerField();
    public static final Field<String> STRING = new StringField();

    //private ctor
}

or if you prefer

public final class Fields {
    public static Field<Integer> integerField() {
        return new IntegerField();
    }
    
    public static Field<String> stringField() {
        return new StringField();
    }

    //private ctor
}

Why would I want to call Fields.INTEGER.get() when I can just use Fields.INTEGER?

like image 24
Michael Avatar answered Aug 09 '26 16:08

Michael



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!