8

复制器:

enum IDs {
    ID {

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

    void getId() {}

    private static void w() {}
}

发出警告:

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

我了解合成方法是什么——我没有得到的是它们如何与枚举一起发挥作用——我希望枚举实例具有我在枚举中定义的所有私有方法。实例真的是嵌套类吗?

4

1 回答 1

3

正如您在此处所做的那样,定义方法的枚举实例ID是枚举类的隐式匿名子类的单例。正常的访问规则适用于子类和枚举类之间,因此需要合成访问器来查看枚举类的私有特性。

Java 语言规范要求枚举以这种方式工作

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

这当然是它们的实际实施方式。在 JDK 的 javac 中,这发生在JavacParser::enumeratorDeclaration第 3344 行左右(在此版本中):

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解析类体( ),然后将其用作实例创建表达式 ( )中的类体. 如果您愿意,您可以完成节点的编译,但就像它的 javadoc 所做的那样,它可以建模:classOrInterfaceBody(...)names.emptyNewClass(..., body)JCNewClass

 * A new(...) operation.

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

于 2013-10-19T11:34:05.150 回答