How do I call individual methods of an Enum?
I have an enum that might look like below. My goal is to have enum
with some common methods (I applied this by adding an abstract method) and some "enum value individual" methods.
The following code compiles:
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();
}
}
Running this result will be printed like this:
VALUE syso
SPECIAL_VALUE syso
However, the call attempt sayHello()
that I defined in SPECIAL_VALUE
does not work.
Adding the following to the main method no longer compiles:
public static void main(String... args) {
MyEnum.SPECIAL_VALUE.sayHello(); // does not work
}
Why? I think this is fine, but no method was found. Is there a way to call this method? Maybe through a reflection?
I would also like this method to be abstract because it doesn't make sense for any other enum values. I also cannot extend
list and add this special method, inheriting the general ones. I would also like to avoid adding some sort of singleton class to "simulate" this.
Can this be run? If not, what's my best alternative?
source to share
Why is this?
The reason is given in the JLS :
8.9.1. Account Assignment Constants
...
Instance methods declared in the bodies of an enum class can only be called outside the enclosing enum type if they override the available methods in the enclosing enum type (ยง8.4.8) .
Is there a way to call this method? Maybe through a reflection?
Given the above limitation, reflection is the only alternative if you don't want to expose the method in the enclosing enum class. Each enum constant is generated as an inner class, for example MyEnum$1
, and MyEnum$2
in your example. So, you can get Class
through the constant method getClass()
and then call the method with the reflection method (exception handling exception):
...
Class c = MyEnum.SPECIAL_VALUE.getClass();
Method m = c.getMethod("sayHello");
m.invoke(MyEnum.SPECIAL_VALUE);
...
I would most likely try to avoid reflection and expose the method in the enum class and let it throw UnsupportedOperationException
:
...
public void sayHello() {
throw new UnsupportedOperationException();
}
...
This at least catches unintended calls at runtime - it still prevents the compiler from catching them at compile time, but the approach is not appropriate either.
source to share
Since it SPECIAL_VALUE
is an instance enum
, enum
it only has a method syso()
. you call
It's the same with classes:
interface Foo {
Foo inst1 = new Foo() {
@Override
public void doFoo() {
}
public void doAnonymous() {
}
};
void doFoo();
}
You cannot call the doAnonymous () method like Foo.inst1.doAnonymous () and you can only access doAnonymous through reflection
source to share