3

I would like someone to explain the compilation error this file causes:

public enum TestEnum {
    A {
        @Override
        void someMethod() {
            System.out.println("A: " + x);
        }
    },
    B {
        @Override
        void someMethod() {
            System.out.println("B: " + x);
        }
    };
    private int x;
    abstract void someMethod();
}

The compilation error is:

TestEnum.java:11: error: non-static variable x cannot be referenced from a static context
        System.out.println("B: " + x);

If I remove the private modifier, the class compiles without error. This seems to imply that someMethod is a static context (is it?) and that removing the access modifier on int x makes it a static variable (does it?). Why is this the case?

Environment:

  • java version "1.8.0_51"

p.s. I'm trying to initialize a Properties field in the enum constructor, which delegates to an abstract init method of each enum instance. That's where I'm running into the above error message. I don't want x/properties to be a static field; it should be unique for each enum instance.

Duplicate counter-argument

How to use fields in java enum by overriding the method?

To start, if you don't mind an appeal to an authority, Jon Skeet commented on that question by saying "That's very odd - I'm surprised that the override counts as a static context. Note that making the field protected removes the error, which is also odd..."

As far as I can tell in Rafael's excellent answer, he never addresses this oddity. Yes, A and B are equivalent to static nested classes, but a static inner class is roughly equivalent to a normal top-level class: it does not mean that the all of the methods and fields of the class are static as well. Are the methods of enums in static context? So in Rafael's answer, the doIt methods are actually static methods even though they are not marked as such?

Community
  • 1
  • 1
DavidS
  • 5,022
  • 2
  • 28
  • 55
  • 1
    I suspect it's because each enum value, such as `A` and `B`, is compiled as a subclass of `TestEnum`. Subclasses cannot access the parent's private fields. – Nayuki Aug 11 '15 at 23:15
  • But why does the error message say that `someMethod` is a static context, @NayukiMinase? I understand that an enum instance is roughly equivalent to a static nested class, but that doesn't make all of its method static too, does it? – DavidS Aug 11 '15 at 23:41
  • 'Static inner' is a contradiction in terms. You mean 'static nested'. – user207421 Aug 11 '15 at 23:43
  • Corrected, thanks @EJP. – DavidS Aug 11 '15 at 23:44
  • 1
    don't worry about the error message - when a code doesn't compile, the compiler has to guess the intention of the programmer. this cannot be accurate. – ZhongYu Aug 11 '15 at 23:45
  • That makes sense, @bayou.io, though it's a bit disappointing that the message is a total red herring. I hope someone will contradict you :-) – DavidS Aug 11 '15 at 23:46
  • the message might be the correct one for another programmer who intended to, but forgot to, declare the field 'static' :) – ZhongYu Aug 12 '15 at 00:30

1 Answers1

1

Try this

     ((TestEnum)this).x

The error message is a misleading. The problem is, private field is not inherited, therefore x or this.x won't compile. You have to up-cast it to the superclass to access it.

see also https://groups.google.com/d/msg/java-lang-fans/KVmmgeSCHkA/Kr_KxaaeolIJ

The 'protected' access is probably better here

    protected int x;
ZhongYu
  • 19,446
  • 5
  • 33
  • 61