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?

+3


source to share


2 answers


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.

+6


source


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

+1


source







All Articles