TL;DR It's hard to imagine a real-world situation where defining an inner class inside of an enum constant makes sense.
Let's start from your code example...
public enum Status {
SUCCESS("SUCCESS") {
},
FAILED("FAILED") {
class Test {
public void test() {
System.out.println("test");
}
}
};
private String code;
Status(String code) {
this.code = code;
}
}
As FAILED
is an enum value with a body, it becomes an anonymous subclass of the Status
enum class. And Test
is defined inside this anonymous class. Because of the anonymous nature of its enclosing class, there's no way to express its name from outside of FAILED
. It surely isn't Status.FAILED.Test
.
So Test
is mainly useful inside of FAILED
(if FAILED
's implementation is complex enough to warrant an inner class). Generally, I'd prefer enum constants to not become that complex, but that's a matter of style.
An access to Test
from outside of FAILED
is only possible through a superclass or interface that Test
extends / implements, and only to methods exposed through that superclass or interface.
A (contrived) example showing both a usage inside and outside of FAILED
, might be:
public class StatusTest {
enum Status {
FAILED{
class Test implements Runnable {
private String text = "Test " + System.currentTimeMillis();
@Override
public void run() {
System.out.println(text);
}
}
@Override
public Runnable getRunner() {
return new Test();
}
@Override
public void message() {
getRunner().run();
}
};
public abstract void message();
public abstract Runnable getRunner();
}
public static void main(String[] args) {
Status status = Status.FAILED;
status.message();
Runnable runner = status.getRunner();
runner.run();
}
}
(Added later)
Of course, in this example there's no reason why the Runnable should get a class name. I'd typically use a named inner class instead of an anonymous one only if it's
- used in multiple places or
- so complex that it would make the enclosing method unreadable.
That's always the same decision when introducing an anonymous vs. a named inner class. With enums there's even less reason to give the inner class a name, as this name isn't usable outside. So, if I were to see a code like above, I'd refactor it to use an anonymous class:
public class StatusTest {
enum Status {
FAILED {
@Override
public Runnable getRunner() {
return new Runnable() {
private String text = "Test " + System.currentTimeMillis();
@Override
public void run() {
System.out.println(text);
}
};
}
@Override
public void message() {
getRunner().run();
}
};
public abstract void message();
public abstract Runnable getRunner();
}
public static void main(String[] args) {
Status status = Status.FAILED;
status.message();
Runnable runner = status.getRunner();
runner.run();
}
}
In both cases, the inner class itself isn't visible to outside code, only inside the enum constant, and if the enum constant's implementation gets so complex that it warrants a named inner class, I'd surely refactor it, e.g. by delegating the complexity to some normal top-level class.