【问题标题】:Enum with generic base class passed as contructor parameter具有作为构造函数参数传递的泛型基类的枚举
【发布时间】:2021-11-12 22:17:23
【问题描述】:

我正在尝试创建一个enum,它的构造函数接受一个基类是泛型类的对象。

我似乎无法从 enum 中获取底层泛型类型,但返回的是 Object 而不是 T

有没有办法做到这一点?

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

【问题讨论】:

    标签: java generics


    【解决方案1】:

    问题是枚举不能被一般类型化,所以即使你强制调用 get 调用 ((T) field.get()) 你也不会有类型安全,因为它会同意任何赋值(你可以成功编译它,例如: boolean b = Fields.INTEGER.get())。

    只需使用常量:

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

    【讨论】:

    • 这是我最初的开始,但希望我可以enum-ify 让事情更有条理。值得一试。 :P
    • @Ian 我真的不明白它是如何“更有条理”的。我认为这种区别存在于你的脑海中,而不是现实中。如果没有理由将字段或参数声明为 Fields 类型,那么作为枚举没有意义。在您的情况下,没有理由这样做,因为您已经可以使用类型 Field&lt;?&gt; 来表达相同的想法。如果您想将Field 的实现者限制为某个有限集,您可以使用Java 17 中的sealed classes
    • 一个例子可能是枚举表示一个数据库表及其列。如果我想创建一个只接受来自该特定表而不接受其他表的字段的函数,我需要像枚举这样的东西。使用静态成员方式,我需要一个通用的基类/接口。无论如何,我显然必须使用静态成员方法,但我仍然希望我可以使用枚举。
    【解决方案2】:

    为什么你认为枚举比这个更可取?

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

    或者如果你喜欢

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

    既然可以使用Fields.INTEGER,为什么还要打电话给Fields.INTEGER.get()

    【讨论】:

    • 我最初是从静态字段方法开始的,但由于每个字段直接相关,而一堆静态字段的内聚性较差......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    相关资源
    最近更新 更多