Являются ли экземпляры enum "вложенными" в тип enum в java?
Репродуктор:
enum IDs {
ID {
@Override
void getId() {
w(); // warning here
}
};
void getId() {}
private static void w() {}
}
Предупреждение выпущено:
Доступ к вмещающему методу w() из идентификаторов типов эмулируется синтетическим методом доступа
Я понимаю, что такое синтетические методы - я не понимаю, как они вступают в игру с перечислениями - я ожидаю, что экземпляры перечисления будут иметь все частные методы, которые я определяю в перечислении. Являются ли экземпляры действительно вложенными классами?
1 ответ
Экземпляр enum, который определяет методы, как ваш ID
делает здесь, является синглтоном неявного анонимного подкласса класса enum. Обычные правила доступа применяются между подклассом и классом enum, поэтому синтетический метод доступа необходим для просмотра закрытых функций класса enum.
Спецификация языка Java требует перечисления для работы следующим образом:
Необязательное тело класса константы enum неявно определяет объявление анонимного класса (§15.9.5), которое расширяет непосредственно включающий тип enum. Тело класса регулируется обычными правилами анонимных классов...
Это, конечно, как они на самом деле реализованы. В Javak JDK это происходит в 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
) в объявлении, то тело класса анализируется (classOrInterfaceBody(...)
) для анонимного класса (names.empty
), и это затем используется как тело класса в выражении создания экземпляра (NewClass(..., body)
). Вы можете следить за составлением JCNewClass
узлы, если хотите, но достаточно сказать, как это делает его javadoc, что он моделирует:
* A new(...) operation.
И, как вы знаете, new
работа с телом класса создает анонимный класс.