... until the collector arrives ...

This "blog" is really just a scratchpad of mine. There is not much of general interest here. Most of the content is scribbled down "live" as I discover things I want to remember. I rarely go back to correct mistakes in older entries. You have been warned :)

2012-09-13

Java Enums and Superclasses vs. Private Members

Consider the following Java Enum definition:

public enum JavaEnumBug {

    VALUE() {
        @Override
        int value() {
            return _id;
        }
    };

    private int _id = 123;

    abstract int value();

}

The Java compiler will complain about the reference to _id in the implementation of value():

Cannot make a static reference to the non-static field _id

This error message is very strange. There is no static reference to the field. There are two ways to make this message go away. The first is to drop the private modifier from the field _id. The second is to change the reference in value() from _id to super._id.

Apparently, Sun/Oracle is aware of this problem as it is listed on the Bug Parade as bug #7119746. That bug is marked as Closed, Not a Defect. The argument starts by observing _id is not visible through the inheritence chain due to being private. This is readily confirmed by changing the reference to _id to this._id whereupon the error message becomes:

The field JavaEnumBug._id is not visible

The bug diagnosis then goes on to argue that even though the reference is visible through class containment, that reference is considered to be static "since [VALUE] is declared as static in [JavaEnumBug]". I find this claim to be unconvincing. VALUE is indeed static, but it is a static reference to an honest-to-goodness subclass of JavaEnumBug. The instance itself has a perfectly well-defined _id field in the superclass, and that field is visible under the rules of enclosing scopes.

So why does super._id work? The reason is that despite all the previous complaining about _id being private from subclasses, it turns out that Java has a back door for accessing private members in superclasses:

abstract class Base {
    private int _id = 123;
}

class Sub extends Base {
    int value() {
       return super._id;
    }
}

According to section 6.6.1 of the Java Language Specification, super._id should not be visible in Base. But it is -- another bug. A bug that is convenient for the original problem, however.

Blog Archive