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