如何调用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
但是,尝试调用我在SPECIAL_VALUE
定义的sayHello()
是行不通的。
将以下内容添加到main方法中,不再编译:
public static void main(String... args) { MyEnum.SPECIAL_VALUE.sayHello(); // does not work }
这是为什么? 对我来说似乎完全没问题,但找不到方法。 有没有办法调用这个方法? 也许通过反思?
我想避免使这个方法变得抽象,因为它对任何其他枚举值都没有意义。 我也无法extend
这个枚举并添加这个特殊的方法,同时inheritance常见的方法。 我还想避免添加某种单例类来“模拟”这个。
无论如何可以运行它? 如果没有,那么什么是我最好的选择呢?
这是为什么?
原因在JLS中给出:
8.9.1。 枚举常量
…
枚举类主体中声明的实例方法只有在覆盖枚举类型(第8.4.8节)中覆盖可访问方法时才可以在封闭枚举类型之外调用 。
有没有办法调用这个方法? 也许通过反思?
鉴于上述约束,如果您不希望在封闭的枚举类中公开该方法,则reflection是唯一的替代方法。 每个枚举常量都创建为内部类,例如MyEnum$1
和MyEnum$2
。 因此,您可以通过常量的getClass()
方法检索Class
,然后通过reflection调用您的方法(省略exception处理):
... Class c = MyEnum.SPECIAL_VALUE.getClass(); Method m = c.getMethod("sayHello"); m.invoke(MyEnum.SPECIAL_VALUE); ...
我很可能会尝试避免reflection并在枚举类中公开该方法,并让它抛出UnsupportedOperationException
:
... public void sayHello() { throw new UnsupportedOperationException(); } ...
这至少会在运行时捕获非预期的调用 – 它仍然不允许编译器在编译期间捕获它们,但reflection方法也不会。
因为SPECIAL_VALUE
是enum
的实例, enum
只有方法syso()
你正在调用
类与以下内容相同:
interface Foo { Foo inst1 = new Foo() { @Override public void doFoo() { } public void doAnonymous() { } }; void doFoo(); }
你不能像Foo.inst1.doAnonymous()一样调用方法doAnonymous(),你只能通过reflection访问doAnonymous