我的枚举可能看起来像下面的那个。我的目标是使用一些常用方法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
这个枚举并添加这个特殊的方法,同时继承常见的方法。我还想避免添加某种单例类来模拟"模拟"此
无论如何可以运行吗?如果没有,那么什么是我最好的选择呢?
答案 0 :(得分:7)
为什么?
原因在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);
...
我很可能会尝试避免反射并在枚举类中公开该方法,并让它抛出UnsupportedOperationException
:
...
public void sayHello() {
throw new UnsupportedOperationException();
}
...
这至少会在运行时捕获非预期的调用 - 它仍然不允许编译器在编译期间捕获它们,但反射方法也没有。
答案 1 :(得分:1)
因为SPECIAL_VALUE
是enum
的实例而enum
只有方法syso()
。您正在调用
以下是类的相同内容:
interface Foo {
Foo inst1 = new Foo() {
@Override
public void doFoo() {
}
public void doAnonymous() {
}
};
void doFoo();
}
您不能像Foo.inst1.doAnonymous()那样调用方法doAnonymous(),并且只能通过反射访问doAnonymous