枚举实例是否“封闭”在java中的枚举类型中?

时间:2013-10-19 10:56:03

标签: java enums jvm java-synthetic-methods

复制者:

enum IDs {
    ID {

        @Override
        void getId() {
            w(); // warning here
        }
    };

    void getId() {}

    private static void w() {}
}

发出警告:

  

从类型ID访问封闭方法w()由合成访问器方法

模拟

我理解合成方法是什么 - 我没有得到的是它们如何与枚举结合 - 我希望枚举实例具有我在枚举中定义的所有私有方法。实例是否真的是嵌套类?

1 个答案:

答案 0 :(得分:3)

定义方法的枚举实例,就像你的ID所做的那样,是枚举类的隐式匿名子类的单例。普通访问规则适用于子类和枚举类之间,因此需要使用合成访问器来查看枚举类的私有功能。

Java语言规范requires enums to work this way

  

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

这肯定是他们实际实施的方式。在JDK的javac中,这发生在第3344行的JavacParser::enumeratorDeclaration中(在此版本中):

JCClassDecl body = null;
if (token.kind == LBRACE) {
    JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
    List<JCTree> defs = classOrInterfaceBody(names.empty, false);
    body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
}
if (args.isEmpty() && body == null)
    createPos = identPos;
JCIdent ident = F.at(identPos).Ident(enumName);
JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);

如果声明中有一个左大括号(LBRACE),那么相关位将解析一个类主体(classOrInterfaceBody(...)),用于匿名类(names.empty ),然后将其用作实例创建表达式(NewClass(..., body))中的类主体。如果你愿意,你可以按照JCNewClass节点的编译进行编译,但它足以说明,正如它的javadoc那样,它模型化了:

 * A new(...) operation.

如您所知,带有类主体的new操作会创建一个匿名类。