Reputation: 81761
The syntax sugar provided by Java's enum
facility can sometimes be a little confusing. Consider this example, which does not compile:
public enum TestEnum {
FOO("foo") {
public void foo() {
helper(); // <- compiler error
}
};
String name;
TestEnum(String name) {
this.name = name;
}
public abstract void foo();
private void helper(){
// do stuff (using this.name, so must not be static)
}
}
Can anyone explain why the compiler says
Non-static method 'helper()' cannot be referenced from a static context
How exactly is this context static?
You can make this compile by changing the call to this.
helper()
(here is one confusing point: if we really are in a "static context" like the compiler suggests, how can "this
" work?) or by increasing the visibility of helper()
to default level. Which would you prefer? Also, feel free to suggest a better question title :-)
Edit: I found some discussion about this - but no real answers. My colleague thinks the fact that that this.helper()
works is actually a compiler bug. And indeed with newer Java versions it seems not to work (although super.helper()
does): "cannot find symbol helper()". (Although there's something odd going on: after trying with different Java versions I can't get this.helper()
to compile again with any of them...)
Upvotes: 11
Views: 4789
Reputation: 4769
If I translate your enum into its class structure it will look approximately like this:
public abstract class TestEnum {
public static final TestEnum FOO = new FOO("foo") {
public void foo() {
helper(); // <- compiler error
}
};
String name;
TestEnum(String name) {
this.name = name;
}
public abstract void foo();
private void helper(){
// do stuff (using this.name, so must not be static)
}
}
The instance FOO is an anynomous class that extends TestEnum. That's why I believe you can't access helper(), because it is private. So this.helper() probably shouldn't work. I'm not sure why even super.helper() works, but maybe enum gives you private access to the parent.
As for the static context error, I agree the error message doesn't seem to make sense.
Upvotes: 2
Reputation: 33949
You can think of each enum constant as the only instance of a sub-class of the enum class. Just like with "regular" classes, the enum "sub-classes" cannot access private members of the enum "super-class." (I can't recreate the "this." work-around that you mention.)
A reasonable solution is to change the method access from private to protected to give access to the enum constant "sub-classes."
Better question title suggestion: "Java private enum method?" or just "Private enum method" (let the Java tag take care of the Java-ness)
Upvotes: 1
Reputation: 27793
The error message is misleading, just make helper
protected and it will work.
protected void helper(){
// can be called from subclasses (such as FOO) since it is not private
}
Upvotes: 8
Reputation: 147164
Something like this is covered in the Java Puzzlers book. IIRC, the outer class context is always looked at before the super class. In this case helper is found. But we are constructing the value in a static context (there's effectively a private static final
before FOO
). Hence the error.
Try super.helper();
.
Upvotes: 3