我的枚举可能看起来像下面的那个.我的目标是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();
}
}
Run Code Online (Sandbox Code Playgroud)
运行此结果会打印以下内容:
VALUE syso
SPECIAL_VALUE syso
Run Code Online (Sandbox Code Playgroud)
但是,尝试调用sayHello()(我定义的SPECIAL_VALUE)不起作用.
将以下内容添加到main方法中,不再编译:
public static void main(String... args) {
MyEnum.SPECIAL_VALUE.sayHello(); // does not work
}
Run Code Online (Sandbox Code Playgroud)
这是为什么?对我来说似乎完全没问题,但找不到方法.有没有办法调用这个方法?也许通过反思?
我想避免将这个方法抽象化,因为它对任何其他枚举值都没有意义.我也不能extend这个枚举并添加这个特殊的方法,同时继承常见的方法.我还想避免添加某种单例类来"模拟"这个.
无论如何可以运行它?如果没有,那么什么是我最好的选择呢?
这是为什么?
原因在JLS中给出:
8.9.1.枚举常量
...
只有当它们覆盖封闭枚举类型(第8.4.8节)中的可访问方法时,才可以在封闭枚举类型外部调用在枚举类主体中声明的实例方法.
有没有办法调用这个方法?也许通过反思?
鉴于上述约束,如果您不希望在封闭的枚举类中公开该方法,则反射是唯一的替代方法.每个枚举常数作为一个内部类,就像创建MyEnum$1和MyEnum$2在你的榜样.因此,您可以Class通过常量的getClass()方法检索,然后通过反射调用您的方法(省略异常处理):
...
Class c = MyEnum.SPECIAL_VALUE.getClass();
Method m = c.getMethod("sayHello");
m.invoke(MyEnum.SPECIAL_VALUE);
...
Run Code Online (Sandbox Code Playgroud)
我很可能会尝试避免反射并在枚举类中公开该方法,并让它抛出UnsupportedOperationException:
...
public void sayHello() {
throw new UnsupportedOperationException();
}
...
Run Code Online (Sandbox Code Playgroud)
这至少会在运行时捕获非预期的调用 - 它仍然不允许编译器在编译期间捕获它们,但反射方法也不会.
| 归档时间: |
|
| 查看次数: |
7705 次 |
| 最近记录: |