Cannot make a static reference to the non-static field memberVariable with private variable

The error message is confusing.

The problem is that when you give an enum value code, you are creating an anonymous sub class of the enum. (Its class will be EnumWithAbstractMethodAndMembers$1) A sub-class cannot access the private members of its super-class, however nested classes can via generated accessor method. You should be able to access the private field, and the error message it gives you appears to be mis-leading.

BTW You can use this, but you shouldn't need to IMHO.

    public int addValue(final int value) {
        return super.memberVariable + value;
    }

Here is a shorter example I will log as a bug in the error message as it doesn't lead to a solution to the problem.

public enum MyEnum {
    One {
        public int getMemberVariableFailes() {
            // error: non-static variable memberVariable cannot be referenced from a static context
            return memberVariable;
        }

        public int getMemberVariable2OK() {
            return memberVariable2;
        }

        public int getMemberVariableOK() {
            return super.memberVariable;
        }
    };

    private final int memberVariable = 1;
    final int memberVariable2 = 1;
}

Based on Tom Hawkin's feedback, this example gets the same error message.

public class MyNotEnum {
    // this is the static context in which the anonymous is created
    public static final MyNotEnum One = new MyNotEnum() {
        public int getMemberVariableFailes() {
            // error: non-static variable memberVariable cannot be referenced from a static context
            return memberVariable;
        }

        public int getMemberVariableOK() {
            return super.memberVariable;
        }
    };
    private final int memberVariable = 1;
}

for comparison

public class MyNotEnum {
    public class NestedNotEnum extends MyNotEnum {
        public int getMemberVariableFailes() {
            // compiles just fine.
            return memberVariable;
        }

        public int getMemberVariableOK() {
            return super.memberVariable;
        }
    }
    private final int memberVariable = 1;
}

A similar issue is covered by Puzzle 92 (Twisted Pair) in Java Puzzlers by Josh Bloch and Neal Gafter.

It's nothing special about enums. Any anonymous (or local) inner class in a static context will do. The rules are that the outer class is considered before the super class. This makes a lot of sense for such classes in a non-static context. If changing the context to static changed which variable was looked up, the is the potential to introduce "confusion" at runtime (C++ is much more aggressive with this kind of rule).

An inner class that extends an outer class has access to the private instance fields of the outer class, whether through this or some other instance.

As we are allowed access, we need to somehow specify we want to go through the inner this rather than outer this. As Peter Lawrey points out super.member will do. You can also select the inner this, and then use that expression:

        return ((EnumWithAbstractMethodAndMembers)this).memberVariable + value;

Or

        EnumWithAbstractMethodAndMembers innerThis = this;
        return innerThis.memberVariable + value;

Tags:

Java

Enums