| 目次 | 前項目 | 次項目 | 内部クラス仕様 |
.' を `/' で置き換え、(パッケージ名が null でなければ)別の `/' と簡単な名前 T を後に付けて、パッケージ名として定義します。T のバイトコード名はまた、T の本体内で定義されるすべてのクラスのバイトコード名の前置として働きます。
別のクラスの非 private メンバであり、どのブロックまたは private クラスにも(直接または間接に)含まれないクラス C のバイトコード名は、即座に親クラスのバイトコード名として定義されます。このバイトコード名は `$' と簡単な名前 C が後に付きます。
他のすべてのクラスは、アクセス不可能と呼ばれます。アクセス不可能クラス N は、決して他のコンパイル単位のコードによって参照できません。こうして、コンパイラが同じコンパイル単位の他のクラスと衝突しないように N の名前を選択する限り、その名前はグローバルに一意です。それは、その前置(以前に必要になったように)が、それが発生するパッケージメンバに対して一意だからです。
ツールのために、アクセス不可能クラス N の名前付けについて、いくつかの補足用件があります。このバイトコード名は親クラス(メンバの場合は即座に親クラス)のバイトコード名に、`$' とコンパイラが選択した正の 10 進数字、または `$' と簡単な名前 N 、または両方が(この順番で)後に付きます。さらに、ブロック local N のバイトコード名は、結果の名前を一意にする場合には、親パッケージメンバ T、文字 `$1$' および N から構成します。
Class の getName メソッドが生成する文字列は、これらの
ケースのすべてにおいて、`/' を `.' で置き換えてバイトコード名から引き出されます。これを Java ソースコードに似せるために、名前を「掃除」しようとはしません。
InnerClassesCONSTANT_Class 入力を経由して)パッケージメンバでないクラスまたはインタフェースのバイトコード名を参照する可能性があります。その場合、バイトコードにはまた、これらの名前のエンコーディングを宣言する InnerClasses と呼ばれるクラス属性が入っている必要もあります。この属性は各エンコード名に対して 1 つ、次のレコードの配列を含みます:
各配列要素はエンコード名、定義スコープ、簡単な名前、および当初宣言され、変形されていないアクセスフラグのビットマスクを付けてクラスを記録します。内部クラスがメンバでない場合、その outer_class_info_index はゼロです。クラスが匿名の場合、その inner_name_index はゼロです。
クラス C が protected と宣言された場合、public アクセスフラグビットはC のaccess_flags フィールドにセットされたとしても、InnerClasses レコード内で清掃されます。
レコードの outer_class_info_index は自分自身パッケージメンバでないクラス E を参照し、同じ InnerClasses 属性の前のレコードは E を記述する必要があります。
クラスが型であるメンバを持つ場合、この型の各々にレコードを付けた InnerClasses 属性を持つ必要があります。既に与えられた規則は、パッケージメンバでないクラスが、それに対してレコードを持つ InnerClasses 属性、および最も外側のものを除く親クラスのすべてを持つことを暗示します。
これらの規則は、コンパイラとデバッガが分解せずに、また内部クラス定義を調べるために追加のファイルを開くことなしに、正しくバイトコードを解釈できることを保証します。コンパイラはアクセス不可能クラスに対して InnerClasses レコードを省略できますが、すべてのクラスにレコードを含めるように推奨されます。特にコードをデバッガで使用するためにコンパイルするときがそうです。
Syntheticprivate であり、さもなければパッケージスコープ程度です。
バイトコードを生成するとき、Java 1.1 コンパイラはソースコードで直接定義されてい
ないフィールドまたはメンバすべてを、 Synthetic という名前の属性でマークするように要求されます。(現在、長さはゼロでなければなりません。) これによって、他のコンパイラが private でない覆い隠されたメンバに不注意なソースレベルの参照をしないようにし、ツールが不必要にこれらを表示しないようにできます。
(局所変数を Synthetic であると宣言するための対応する機構を、また導入する可能性があります。)
Java 1.1 コンパイラは、内部クラスを実装するとき次の名前付け規則を使用するように、要求はされないとしても強く薦められます。コンパイラは、他の目的で個々で定義した合成名を使用してはいけません。
最も外側の親インスタンスにポイントする合成フィールドは this$0 と名付けられます。次に外側の親インスタンスは this$1 などとなります。(このようなフィールドがせいぜい 1 つ、すべての与えられた内部クラスに必要です。) 定数 v のコピーを含む合成フィールドは val$v と名付けられます。これらのフィールドは final です。
これら合成フィールドのすべては、初期化するフィールドと同じ名前を持つ構築子パラメータによって初期化されます。パラメータの 1 つが最奥の親インスタンスの場合、これが最初になります。このような構築子パラメータのすべては合成になります。コンパイラが合成フィールド値を構築子のコードの中だけで使用すると決めた場合、フィールド自身を省略し、パラメータだけを使用して変数参照を実装します。
private メンバまたは構築子へのアクセスを供与する private でない final 合成メソッドは、access$N という形式の名前を持ちます。ここで、N は 10 進数字です。このようなアクセスプロトコルの組織は指定されていません。
1.1 互換のデバッガおよび同様のツールは、これらの名前付け規則を認識し、変数表示とシンボルテーブルをこれにしたがって編成する必要があります。ツールがこれらの名前を分解する必要があることに注意してください。コンパイラは少なくともデフォルトで、これらの規則を使用するよう強く薦められます。
Java Virtual Machine の実装は変化し、ここで指定される合成メンバが正しく定義され、使用されるように要求する可能性があります。最適化技術を合成メンバに適用して、その性質を開拓することは理にかないます。
内部クラス仕様 (HTML generated by dkramer on March 15, 1997)
Copyright (c) 1996, 1997 Sun Microsystems, Inc.
All rights reserved
コメントや訂正は john.rose@eng.sun.com 宛てに送ってください。