为什么枚举实现不能访问枚举类中的私有字段

时间:2014-07-29 08:25:09

标签: java enums

我刚刚回答了这个问题,说明如何解决编译问题:

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

但我不明白的是为什么错误发生在第一位。

以下是以枚举形式编写的示例:

public enum MyEnum {


    FIRST {
        @Override
        public String doIt() {
            return "1: " + someField; //error
        }
    },
    SECOND {
        @Override
        public String doIt() {
            return "2: " + super.someField; //no error
        }
    };

    private String someField;


    public abstract String doIt();

} 

这与抽象类

完全相同
abstract class MyClass {
    class FIRST extends MyClass {
        @Override
        public String doIt() {
            return "1: " + someField; //no error
        }
    };
    class SECOND extends MyClass {
        @Override
        public String doIt() {
            return "2: " + super.someField; //no error
        }
    };

    private String someField;

    public abstract String doIt();
}

对于FIRST实施中的enum,它无法访问someField。但是在抽象类的情况下它可以。

此外,添加super可以解决问题,就像删除字段上的private修饰符一样。

有谁知道为什么这种轻微的怪癖正在发生?

4 个答案:

答案 0 :(得分:15)

您的抽象类不等同于您的枚举,因为枚举是隐式公共静态最终的。因此,如果您使用:

,您将观察到相同的行为
abstract class MyClass {

    static class FIRST extends MyClass {

        @Override
        public String doIt() {
            return "1: " + someField; // error
        }

    };

    static class SECOND extends MyClass {

        @Override
        public String doIt() {
            return "2: " + super.someField; // no error
        }

    };

    private String someField;

    public abstract String doIt();

}

http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html中所述,章节"静态嵌套类":

  

静态嵌套类不能直接引用实例变量或   在其封闭类中定义的方法:它只能通过它来使用它们   对象引用。

因此需要super。如果字段为this而非protected,您也可以使用private

答案 1 :(得分:4)

解析标识符时,Java优先考虑继承成员的词法范围。因此,如果您有一个扩展外部类的内部类并使用外部类的字段而不使用thissuper,则访问外部实例的字段,如果内部类为{,则该字段将失败{1}}因为那时没有外部实例。相反,使用static时,您将显式访问继承的成员。请注意,super类隐式enum。您甚至可以使用static来访问继承的成员,但如果声明为this,则必须使用((MyClass)this).someField来访问它。

答案 2 :(得分:0)

FIRSTMyClass的内部类,也是子类。在访问someField时没有看到错误的原因是因为您正在访问外部类的someField,而不是超类。

class MyClass {
    class FIRST extends MyClass {
        @Override
        public String doIt() {
            super.someField = "super";
            return "1: " + someField;
        }
    };

    private String someField = "outer";

    public String doIt(){return "";}

    public static void main(String[] args) {
        System.out.println(new MyClass().new FIRST().doIt());
    }
}

打印1: outer

在另一种情况下,你的枚举常量表现为静态嵌套子类,而不是内部类,因此它们没有对外部类的引用,只有它们的超类。

答案 3 :(得分:0)

我不同意接受的答案。

枚举const声明是隐式public static final,但不是enum const所属的类。

来自JSL Chapter 8.Classes

  

枚举常量的可选类体隐式定义了一个匿名类声明(第15.9.5节),该声明扩展了直接封闭的枚举类型。类主体由匿名类的通常规则管理。

什么是'无限级的规则'?

来自JSL Chapter 15:

  

Java编译器会自动从类实例创建表达式派生出一个匿名类声明。

     

匿名类永远不是抽象的(§8.1.1.1)。

     

匿名类总是隐含最终的(§8.1.1.2)。

     

匿名类始终是内部类(第8.1.3节);它永远不会是静态的(§8.1.1,§8.5.1)。

如果枚举等效类是静态类,如何解释以下错误?

public enum MyClass {
    First {
        public static int b;  //(2)Illegal static declaration in inner class
    };
}

但是为什么内部类不能访问外部类的字段?

可能的枚举等效类可能如下所示,它给出了与枚举类相同的错误:

abstract class MyClass {    
    private int someField;
    static {
        class First extends MyClass {
            public void method() {
                System.out.println(someField);
            }
            private static int b;
        }
    }
}

更多: