I was doing some experiments and accidently wrote a code, which is very weird and I don't get it all. I was even surprised that I can compile it. It looks like this:
enum Foo {
VALUE_1 {
public int myVariable = 1;
},
VALUE_2 {
public void myMethod() {
//
}
},
VALUE_3;
}
As expected, it's not possible to access such an element in the following way:
Foo.VALUE_2.myMethod();
The reason is, that compiler will look for that method inside the enumeration itself.
I presumed that it's not possible to access these methods and variables from outside the enumeration. For this reason, I tried to create a parametric constructor and call it with some internal variable:
enum Foo {
VALUE(internalVariable) {
int internalVariable = 1;
};
private Foo(int param) {
//
}
}
It wasn't possible to compile such a construction. Now I was thinking what's the point of defining something inside the constant if there is no way to access it.
I was trying to create the same-named methods in the constant as well in the enumeration itself to check out if it collides in some way. It didn't!
enum Foo {
VALUE_1 {
int myVariable = 1;
public int myMethod() {
return myVariable;
}
},
VALUE_2 {
//
};
public int myMethod() {
return 0;
}
}
And here comes the funny moment! I tried to proceed call of myMethod() inside the enumeration and actually figured out how this Java magic works. Methods, which are defined inside the constant, overrides methods defined inside the enumeration.
Foo.VALUE_1.myMethod(); // Returns 1
Foo.VALUE_2.myMethod(); // Returns 0
However, we can't override variable, right? So I was curious, how it works with variables only.
enum Foo {
VALUE_1 {
public int myVariable = 1;
},
VALUE_2 {
//
};
public int myVariable = 0;
}
....
System.out.println(Foo.VALUE_1.myVariable); // Returns 0
System.out.println(Foo.VALUE_2.myVariable); // Returns 0
Now I'm finally getting to my questions:
Why I don't get any error if I create public method inside the constant and left enumeration empty without this method? In that case, the method I just defined can't be called at all. Or am I wrong?
Update: I know that enumeration can implement interface. However, if I haven't specifically said that, whole code is pointless.
Someone pointed out that even if method can't be accessed from the language in the normal way, it's still possible to use reflection. Well... Why don't we design an inaccessible keyword?
inaccessible void magicalMethod() { // }
Such a method will be compiled into the *.class file. When you want to use it, you've to load bytecode by yourself and interpret it.
I just can't understand, why it's possible to define unreachable method. The only reason I can think is that programmer is working and doesn't have definition of interface yet. So he's just preparing code of single methods and will add "implements" keyword later. Beside this is illogical, it would still require to have such a method in all constants.
I think this should end up with error, not just warning about unused method. You may forget to add "implement" clause or to define method in the enumeration (which would be overridden) and will realize that just after the first use. Java is very strict language, so I'd expect this behavior.
Why I don't get any error if I create public variable (or field, to be more precise) inside the constant? It can't be accessed in the any case (from the outside). Therefore, modifier "public" doesn't make any sense here.
Update: It's more less the same thing as in the previous point, except the visibility modifier is completely useless here. It really doesn't matter if it's public, protected or private, because you won't be able to access that anyway. I think this is a bug.
Why it's possible to define a class (without visibility modifiers), but not interface? Yeah, you wouldn't probably want to write so brutal enumeration that you would need to define classes inside the constant and even to use inheritance there. But if it's possible to define classes and abstract classes, it seems little weird.
Update: This is definitely not something you'd need on regular basis, but I understand that it might be useful. But why it's limited to classes only and interfaces can't be defined as well?
enum Foo { VALUE { class MyClass { // OK } abstract class MyAbstractClass { // OK } interface MyInterface { // FAIL. It won't compile. } } }
Did you use such a functionality somewhere? I can imagine it might be useful, but it's little confusing. Also, when I was searching for some resources about that, I didn't find anything.
Update: I'd like to see some practical example wth overridden methods in an enum constant class body. Have you seen it in some open-source project?
Environment:
$ java -version
java version "1.7.0_21"
OpenJDK Runtime Environment (IcedTea 2.3.9) (7u21-2.3.9-0ubuntu0.12.10.1)
OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)
Thanks for your time and for your answers!