如何通过枚举管理generics?

我有一个参数化的界面:

public interface MyInterface { void run(T e); } 

和实现接口的类:

 public class MyClass1 implements MyInterface { public void run(SomeOtherClass1 e) { // do some stuff with e } } public class MyClass2 implements MyInterface { public void run(SomeOtherClass2 e) { // do some stuff with e } } 

不同的MyClass * X *的数量是已知且详尽的,并且每个MyClass * X *只有一个实例,所以我想使用枚举:

 public enum MyEnum { MY_CLASS_1, MY_CLASS_2; } 

能够使用MyEnum.MY_CLASS_1.run(someOtherClass1); 例如(我会将MyInterface的每个实例放在同一个地方)。 甚至可能(如果是的话,如何)? 因为我现在很困惑……


我还尝试了什么:

 public enum MyEnum { MY_CLASS_1(new MyClass1()), MY_CLASS_2(new MyClass2()); private MyInterface instance; private MyEnum(MyInterface instance) { this.instance = instance; } public void run(/* WhichType? */ e) { instance.run(e); } } 

在上面的方法中,当使用类型Object作为e参数时:

 public void run(Object e) { instance.run(e); // ^^^ // The method run(capture#3-of ?) in the type MyInterface is not applicable for the arguments (Object) } 

我认为问题在于private MyInterface instance字段:我需要知道如何使用private MyInterface instance等参数化private MyInterface instance ,但我找不到工作解决方案……

简而言之,我被卡住;)


PS:因为run方法体可能很长,所以我试图避免枚举中的匿名类:

 public enum MyEnum { MY_CLASS_1 { /* any method, etc. */ }, MY_CLASS_2 { /* any method, etc. */ }, } 

然后MyEnum变得完全不可读。

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

只有枚举本身可以实现接口,并且必须在枚举级别指定generics,因此在您的情况下,只有Object或这两者的一些通用接口才适用。

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

如果你想保持这些策略是分开的,你仍然需要在枚举中使用run(Object)方法,并且在每个常量中使用一些显式强制转换定义,因为你根本不能为每个枚举实例提供不同的方法签名(或者即使你可以,他们不会从外面看到它们。


提示如何欺骗编译器,如果你真的想这样做而不是为每个实例重新设计或显式转换:

 enum MyEnum implements MyInterface { 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 delegate; MyEnum(MyInterface delegate) { this.delegate = (MyInterface) delegate; } @Override public void run(Object e) { delegate.run(e); } } 

如果您尝试将MyEnum.MY_CLASS_1.run()SomeOtherClass1以外的其他内容一起使用,则上述方法将起作用并且您将获得ClassCastException (如预期的那样)。

正如科斯蒂指出的那样 ,枚举本身不是通用的 。 但是我想我可以确定你的设计出错了:

每个MyClass X只有一个实例,所以我想使用枚举:

 public enum MyEnum { MY_CLASS_1, MY_CLASS_2; } 

你说每个类都是单例。 所以他们实际上每个都应该一个枚举:

 public enum MyClass1 implements MyInterface { INSTANCE; @Override public void run(SomeOtherClass1 e) { // do some stuff with e } } public enum MyClass2 implements MyInterface { INSTANCE; @Override public void run(SomeOtherClass2 e) { // do some stuff with e } } 

这更有意义,因为如果你考虑它,你不需要枚举这两个实现,所以它们不需要一起生活。 只需单独使用Josh Bloch的enum模式就足够了。