如何调用Enum个人方法?

noo*_*one 3 java enums

我的枚举可能看起来像下面的那个.我的目标是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这个枚举并添加这个特殊的方法,同时继承常见的方法.我还想避免添加某种单例类来"模拟"这个.

无论如何可以运行它?如果没有,那么什么是我最好的选择呢?

And*_*ter 8

这是为什么?

原因在JLS中给出:

8.9.1.枚举常量

...

只有当它们覆盖封闭枚举类型(第8.4.8节)中的可访问方法时,才可以在封闭枚举类型外部调用在枚举类主体中声明的实例方法.

有没有办法调用这个方法?也许通过反思?

鉴于上述约束,如果您不希望在封闭的枚举类中公开该方法,则反射是唯一的替代方法.每个枚举常数作为一个内部类,就像创建MyEnum$1MyEnum$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)

这至少会在运行时捕获非预期的调用 - 它仍然不允许编译器在编译期间捕获它们,但反射方法也不会.