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::enumeratorDeclaration3344 行目あたりで発生します (このバージョンでは)。

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 に答える