如何制作一个可以容纳Class <t>的通用枚举?</t>

时间:2014-12-29 11:47:12

标签: java generics enums core

假设我有签名

<T>IInterface<T> method(Class<T> myClass)

是否可以编写可以保存类类型的枚举,以便能够将实例传递给方法?

method(MyEnum.STEP)

STEP是一个班级。

实际上我想改变方法的签名而不是Class<T> myClass而是枚举。但我不想修改返回值类型<T>IInterface<T>

<T>IInterface<T> method(MyEnum type)

1 个答案:

答案 0 :(得分:6)

枚举常量的值始终是一个对象,它是枚举类的一个实例。你不能让它有不同的价值;既不是对类的引用,也不是其他任何内容。

您可以在枚举上添加实例字段,该字段可以包含每个枚举常量所需的任何值:

enum MyEnum {
    STEP(Step.class),
    FOO(Foo.class),
    BAR(Bar.class);

    public final Class<?> klass;

    private MyEnum(Class<?> klass) {
        this.klass = klass;
    }
}

(使用变量名klass,因为class是保留关键字。)

您可以使用以下方式调用此方法:

method(MyEnum.STEP.klass);

但是,它并不保留通用类型信息。对于每个枚举常量,klass字段的类型为Class<?>,因此method(MyEnum.STEP.klass)的返回类型将为IInterface<?>而不是IInterface<Step>

枚举不能是通用的,因此它们的字段对于不同的常量不能有不同的类型。如果您需要在常量中保留泛型类型信息,则必须放弃使用枚举来实现此目的,而是使用类来伪造它。然后,您可以使用不同的类型声明每个常量:

class MyConstant<T> {
    public static final MyConstant<Step> STEP = new MyConstant<>();
    public static final MyConstant<Foo> FOO = new MyConstant<>();
    public static final MyConstant<Bar> BAR = new MyConstant<>();

    private MyConstant() {}
}

这将为您提供几乎所需的方法签名:

<T> IInterface<T> method(MyConstant<T> type)

被调用为:

IInterface<Step> something = method(MyConstant.STEP);

如果您还需要运行时可用的类型信息,则可以将类值作为字段添加到常量上,方法与枚举示例相同:

class MyConstant<T> {
    public static final MyConstant<Step> STEP = new MyConstant<>(Step.class);
    public static final MyConstant<Foo> FOO = new MyConstant<>(Foo.class);
    public static final MyConstant<Bar> BAR = new MyConstant<>(Bar.class);

    public final Class<T> klass;

    private MyConstant(Class<T> klass) {
        this.klass = klass;
    }
}
相关问题