我有一个枚举,可能如下所示。我的目标是拥有一个enum
使用一些常见方法(我通过添加抽象方法来强制执行此操作)和一些“枚举值个体”方法。
以下代码编译:
public enum MyEnum {
VALUE {
@Override
public void syso() {
System.out.println("VALUE syso");
}
},
SPECIAL_VALUE {
@Override
public void syso() {
System.out.println("SPECIAL_VALUE syso");
}
public void sayHello() {
System.out.println("Hello");
}
};
public abstract void syso();
public static void main(String... args) {
MyEnum.VALUE.syso();
MyEnum.SPECIAL_VALUE.syso();
}
}
运行此命令会打印以下结果:
VALUE syso
SPECIAL_VALUE syso
然而试图打电话sayHello()
,我在中定义SPECIAL_VALUE
,不起作用。
将以下内容添加到 main 方法中,不再编译:
public static void main(String... args) {
MyEnum.SPECIAL_VALUE.sayHello(); // does not work
}
这是为什么?对我来说似乎完全没问题,但找不到方法。有什么办法可以调用这个方法吗?也许通过反射?
我也想避免使此方法抽象,因为它对于任何其他枚举值都没有意义。我也不能extend
这个枚举并添加这个特殊方法,同时继承通用方法。我还想避免添加某种单例类来“模拟”这一点。
无论如何可以运行这个吗?如果没有,我最好的选择是什么?
这是为什么?
原因在JLS:
8.9.1.枚举常量
...
枚举类体中声明的实例方法可以在封闭枚举类型之外调用仅当它们覆盖封闭枚举类型中的可访问方法时(第 8.4.8 节).
有什么办法可以调用这个方法吗?也许通过反射?
考虑到上述约束,如果您不想公开封闭枚举类中的方法,那么反射是唯一的选择。每个枚举常量都创建为内部类,例如MyEnum$1
and MyEnum$2
在你的例子中。因此,您可以检索Class
通过常数的getClass()
方法,然后通过反射调用你的方法(省略异常处理):
...
Class c = MyEnum.SPECIAL_VALUE.getClass();
Method m = c.getMethod("sayHello");
m.invoke(MyEnum.SPECIAL_VALUE);
...
我很可能会尝试避免反射并公开枚举类中的方法,并让它抛出一个UnsupportedOperationException
:
...
public void sayHello() {
throw new UnsupportedOperationException();
}
...
这至少可以在运行时捕获意外的调用 - 它仍然不允许编译器在编译时捕获它们,但反射方法也不能捕获它们。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)