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
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 ?
CodePudding user response:
An enum instance which defines methods, as your ID
does here, is a singleton of an implicit anonymous subclass of the enum class. 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:
The optional class body of an enum constant implicitly defines an anonymous class declaration (§15.9.5) that extends the immediately enclosing enum type. 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):
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)
). You can follow through the compilation of JCNewClass
nodes if you like, but it suffices to say, as its javadoc does, that it models:
* A new(...) operation.
And as you know, a new
operation with a class body creates an anonymous class.