The task is to implement beautiful strategy design pattern with the java enum
:
public enum MyEnum { FIRST { @Override public String doIt() { return "1: " + someField; //error } }, SECOND { @Override public String doIt() { return "2: " + someField; //error } }; private String someField; public abstract String doIt(); }
but when referring to someField
I get
Cannot make a static reference to the non-static field someField.
What is wrong and is it possible to do that better?
Duplicates in enum type can be done in 2 ways : Duplicate enum members (2 or more members with same name) 2 or more members with same value.
Enums are exactly final inner classes that extends java. lang. Enum<E> . You cannot extend, override or inherit an enum .
You can use the "new" keyword to override the field you defined in the base class. I used this, and it says it hides the inherited member.
Although the enum type has special behavior in Java, we can add constructors, fields and methods as we do with other classes.
A specialized enum
is nothing but a subclass with inner-class semantics. If you look at the byte code after compilation, you will notice that the compiler only inserts accessor method for reading a private field but any specialized enum is compiled as its own class. You can think about your enum
as being implemented as:
public abstract class MyEnum { private static class First extends MyEnum { @Override public String doIt() { return "1: " + someField; //error } } private static class Second extends MyEnum { @Override public String doIt() { return "2: " + someField; //error } } public static final MyEnum FIRST = new First(); public static final MyEnum SECOND = new Second(); private String someField; public abstract String doIt(); }
As you can see, the same compiler errors occur. Effectively, your problem does not relate to enum
s but to their inner-class semantics.
However, you found a borderline case of the compiler guessing the intend of your code and trying to warn you that what you intend is illegal. In general, the someField
field is visible to any specialized enum
. However, there are two ways of accessing the private
field from an inner class and only one is legal:
private
members are not inherited. You can therefore not access a private
field from this
instance when it was defined in a super class.
For inner classes, members of outer classes are accessible even if they are private
. This is achieved by the compiler by inserting accessor methods to the outer classes which expose the private
fields by accessor methods. A non-static
field can only be accessed if the inner class is non-static
. For enum
s, the inner classes are however always static
.
The later condition is what the compiler complains about:
Cannot make a static reference to the non-static field
someField
You are trying to access a non-static
field from a static
inner class. This is not possible even though the field would be technically visible because of the inner class semantics. You could instruct the compiler explicitly to access the value by reading it from the super class by for example:
public String doIt() { MyEnum thiz = this; return thiz.someField; }
Now the compiler knows that you are trying to access a member of a visible (outer) type instead of erroneously accessing the someField
field of the (non-static) outer class instance (which does not exist). (Similarly, you could write super.someField
which expresses the same idea that you want to go down the inheritance chain and not access an outer instance's field.) The easier solution would however be to simply make the field protected
. This way the compiler is happy about the inheritance visibility and compiles your original setup.
If you make someField
protected instead of private or use super.someField
instead you will be able to access it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With