Java 枚举如何管理泛型?

Java 枚举如何管理泛型?,java,generics,enums,Java,Generics,Enums,我有一个参数化界面: 公共接口MyInterface{ 无效运行(TE); } 和实现接口的类: 公共类MyClass1实现MyInterface{ 公共无效运行(其他1类e){ //用e做一些事情 } } 公共类MyClass2实现MyInterface{ 公共无效运行(其他类别2 e){ //用e做一些事情 } } 不同MyClass*X*的数量是已知且详尽的,每个MyClass*X*只有一个实例,因此我想使用枚举: public enum MyEnum { MY_CLASS_1

我有一个参数化界面:

公共接口MyInterface{
无效运行(TE);
}
和实现接口的类:

公共类MyClass1实现MyInterface{ 公共无效运行(其他1类e){ //用e做一些事情 } } 公共类MyClass2实现MyInterface{ 公共无效运行(其他类别2 e){ //用e做一些事情 } } 不同MyClass*X*的数量是已知且详尽的,每个MyClass*X*只有一个实例,因此我想使用枚举:

public enum MyEnum {
    MY_CLASS_1,
    MY_CLASS_2;
}
公共枚举MyEnum{
我的第一班,
我的班级2;
}
能够使用MyEnum.MY_CLASS_1.run(someOtherClass1)例如(然后我会将MyInterface的每个实例都放在同一个位置)。这是否可能(如果可能,如何实现)?因为我现在很困


我尝试过的是:

公共枚举MyEnum{
MY_CLASS_1(新MyClass1()),
MY_CLASS_2(新MyClass2());
私有接口实例;
私有MyEnum(MyInterface实例){
this.instance=instance;
}
公共作废运行(/*哪种类型?*/e){
实例。运行(e);
}
}
在上述方法中,当将type对象用于
e
参数时:

公共作废运行(对象e){
实例。运行(e);
//       ^^^
//MyInterface类型中的方法运行(capture#3-of?)不适用于参数(对象)
}
我认为问题在于
private-MyInterface-instance
字段:我需要知道如何使用类似
private-MyInterface-instance
的方法参数化实例,但我找不到有效的解决方案

简言之,我被困住了;)


PS:由于
运行
方法主体可能相当长,因此我试图避免枚举中的匿名类:

公共枚举MyEnum{
我的第一堂课{
/*任何方法等*/
},
我的班级2{
/*任何方法等*/
},
}

MyEnum
将变得完全不可读。

这是不可能的。这是我觉得最烦人的枚举限制之一,但您所能做的就是尝试解决它(就像您在Java pre-5.0中所做的那样)

只有enum本身可以实现接口,并且必须在enum级别指定泛型,因此只有
Object
或这两者的某个公共接口才适用于您的情况

在枚举本身内部声明要以多态方式处理的任何方面(在您的示例中是
run()
方法)(并重写每个常量中的行为)通常是最好的解决方法。当然,您需要放宽您的类型安全要求

如果您想将这些策略分开,您仍然需要在枚举中使用
run(Object)
方法,并在每个常量中使用一些显式强制转换来定义该方法,因为每个枚举实例不能有不同的方法签名(或者即使可以,也不能从外部看到它们)


如果您真的想欺骗编译器,而不是重新设计或对每个实例进行显式强制转换,则提示如何欺骗编译器:

enum MyEnum implements MyInterface<Object> {
    MY_CLASS_1(new MyClass1()),
    MY_CLASS_2(new MyClass2());

    // you may also drop generics entirely: MyInterface delegate
    // and you won't need that cast in the constructor any more
    private final MyInterface<Object> delegate;

    MyEnum(MyInterface<?> delegate) {
        this.delegate = (MyInterface<Object>) delegate;
    }

    @Override
    public void run(Object e) {
        delegate.run(e);
    }
}
枚举MyEnum实现MyInterface{ MY_CLASS_1(新MyClass1()), MY_CLASS_2(新MyClass2()); //您也可以完全删除泛型:MyInterface delegate //您将不再需要构造函数中的强制转换 私人接口代表; MyEnum(MyInterface委托){ this.delegate=(MyInterface)delegate; } @凌驾 公开作废运行(对象e){ 代表运行(e); } } 如果您尝试将
MyEnum.MY_CLASS_1.run()
SomeOtherClass1

as以外的其他对象一起使用,则上述操作将起作用,您将得到一个
ClassCastException
(如预期的那样)。但是,我认为我可以确定您在设计中的错误:

每个MyClassX只有一个实例,因此我想使用 枚举:

public enum MyEnum {
    MY_CLASS_1,
    MY_CLASS_2;
}
你是说这些类中的每一个都是单身。因此,它们实际上应该是一个枚举:

public enum MyEnum {
    MY_CLASS_1,
    MY_CLASS_2;
}
公共枚举MyClass1实现MyInterface{ 实例; @凌驾 公共无效运行(其他1类e){ //用e做一些事情 } } 公共枚举MyClass2实现MyInterface{ 实例; @凌驾 公共无效运行(其他类别2 e){ //用e做一些事情 } }
这更有意义,因为如果您仔细想想,您不需要列举这两个实现,因此它们不需要共存。单独使用就足够了。

很好的解释,但我不喜欢这个解决方案,因为它缺乏类型安全性。@PaulBellora:我也不喜欢:)。这甚至不是一个解决方案,只是一个变通办法。它只适用于没有enum功能(遍历值、按名称获取值、序号、切换案例等)的情况@sp00m:我编辑了我的代码示例,将参数化版本显示为第一个选项,以解决您的特定问题:“我需要知道实例是如何参数化的”即使我也不太喜欢它,如果我不想重新设计工作,这可能是唯一的解决办法。。。但我想我最好在没有枚举的情况下重新设计它;)无论如何谢谢你,很遗憾Enum不能管理这些泛型+1这很有意义(例如,这就是
函数
在Guava中的实现方式——出于同样的原因)。但是,如果你真的需要集体引用这些实例,那就有点麻烦了(正如我在另一篇评论中提到的)。实际上,我可以用这些单例来替换MyClass1、MyClass2等,但MyEnum的目的是让MyInterface的所有可用实例都在同一个地方,因为在我的案例中有一个已知的详尽清单。我将更新我的问题,使其更符合c