简体   繁体   English

Java中的枚举类型是否将枚举实例“封闭”?

[英]Are enum instances “enclosed” in the enum type in java?

Reproducer : 复制者:

enum IDs {
    ID {

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

    void getId() {}

    private static void w() {}
}

Warning emitted : 发出警告:

Access to enclosing method w() from the type IDs is emulated by a synthetic accessor method 通过综合访问器方法模拟从类型ID对封闭方法w()的访问

I understand what synthetic methods are - what I do not get is how they come into play with enums - I would expect enum instances to have all private methods I define in the enum. 我了解什么是综合方法-我没有得到的是它们如何与枚举一起使用-我希望枚举实例具有我在枚举中定义的所有私有方法。 Are instances really nested classes ? 实例真的是嵌套类吗?

An enum instance which defines methods, as your ID does here, is a singleton of an implicit anonymous subclass of the enum class. 像您的ID一样,定义方法的枚举实例是枚举类的隐式匿名子类的单例。 The normal access rules apply between the subclass and the enum class, so a synthetic accessor is required to see private features of the enum class. 常规访问规则适用于子类和枚举类之间,因此需要综合访问器才能查看枚举类的私有功能。

The Java Language Specification requires enums to work this way : Java语言规范要求枚举以这种方式工作

The optional class body of an enum constant implicitly defines an anonymous class declaration (§15.9.5) that extends the immediately enclosing enum type. 枚举常量的可选类主体隐式定义了一个匿名类声明(第15.9.5节),该声明扩展了立即封闭的枚举类型。 The class body is governed by the usual rules of anonymous classes... 类主体由匿名类的通常规则控制。

It's certainly how they're actually implemented. 当然,这实际上是它们的实现方式。 In the JDK's javac, this happens in JavacParser::enumeratorDeclaration around line 3344 (in this version): 在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);

The relevant bits there are that if there is a left curly bracket ( LBRACE ) in the declaration, then a class body is parsed ( classOrInterfaceBody(...) ) for an anonymous class ( names.empty ), and this is then used as the class body in an instance creation expression ( NewClass(..., body) ). 相关的位是,如果声明中有左花括号( LBRACE ),则将解析类类( classOrInterfaceBody(...) )为匿名类( names.empty ),然后将其用作实例创建表达式中的类主体( NewClass(..., body) )。 You can follow through the compilation of JCNewClass nodes if you like, but it suffices to say, as its javadoc does, that it models: 如果愿意,可以遵循JCNewClass节点的编译过程,但是足以说明它的javadoc模型:

 * A new(...) operation.

And as you know, a new operation with a class body creates an anonymous class. 如您所知,带有类主体的new操作将创建一个匿名类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM