Java中的枚举实例是否“封装”在枚举类型中?

8

重现:

enum IDs {
    ID {

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

    void getId() {}

    private static void w() {}
}

警告发出:

通过合成访问器方法模拟从类型IDs中访问封闭方法w()

我了解什么是合成方法-我不明白的是它们如何与枚举一起使用-我希望枚举实例具有我在枚举中定义的所有私有方法。实例真的是嵌套类吗?

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),那么将解析一个匿名类(names.empty)的类体(classOrInterfaceBody(...)),然后将其用作实例创建表达式(NewClass(..., body))中的类体。如果您愿意,可以跟踪JCNewClass节点的编译,但正如其javadoc所说,它模拟了:

 * A new(...) operation.

正如你所知,使用带有类体的 new 操作符将创建一个匿名类。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接