型指定子 (type descriptor)
型指定子はクラスファイル上でフィールドやメソッドの型を表現するのに利用される文字列です。
型指定子は型消去されたあとのジェネリクスを含まない型情報を表現します。
よく勘違いしている人がいますが、ジェネリクスを含む型情報は別途 シグネチャ と呼ばれる属性としてクラスファイル上に残っています。
ただ、JVM はシグネチャを無視するため、実行時にはジェネリクスを含む型情報を取得できないのです。
プリミティブ型の型指定子
プリミティブ型の型指定子は各プリミティブ型に対応したアルファベット1文字です。
プリミティブ型とそれに対応する型指定子は以下の表の通りです。
long が L でないのは L がオブジェクト型の型指定子で利用されているためです。(たぶん)
ではなぜオブジェクト型の型指定子に L を使ったのは聞かないで下さい。(class の L ?)
プリミティブ型 | 型指定子 | プリミティブ型 | 型指定子 | |
---|---|---|---|---|
byte | B | int | I | |
char | C | long | J | |
double | D | short | S | |
float | F | boolean | Z |
void 型指定子
void 型の型指定子はメソッドの返り値の型でのみ利用できる特殊なプリミティブ型の型指定子です。
void 型の型指定子は他のプリミティブ型と同様アルファベット1文字で、対応するアルファベットは V です。
オブジェクト型の型指定子
オブジェクト型の型指定子は、先頭の一文字が L で、続いてクラス名、最後に ; (セミコロン) という形式となっています。
クラス名は必ず完全修飾名(パッケージ名を含む完全な名前)で、internal form と呼ばれる形式にエンコードされています。
internal form は '.' の代わりに '/' でパッケージ名を区切ったものです。
例えば、以下は String 型の型指定子です。
Java を使ったことのある方ならどこかで一度は目にしたことがあるのではないでしょうか。
Ljava/lang/String;
配列型の型指定子
配列型の型指定子は、先頭の一文字が [ で、それに配列の中身の型指定子が続くといった形式となっています。
配列の中身の型指定子には、void を除くプリミティブ型の型指定子、オブジェクト型の型指定子、及び配列型の型指定子が利用できます。
例えば、以下は全て配列型の型指定子です。
[I
[Ljava/lang/String;
[[[D
上から順に、int[], String[], double[][][] を表現しています。
フィールドの型指定子
フィールドの型指定子には void を除くプリミティブ型の型指定子、オブジェクト型の型指定子、及び配列型の型指定子が利用できます。
例えば、以下は全てフィールドの型指定子として利用可能です。
I
Ljava/util/List;
[[Ljava/lang/Object;
上から順に、int, List, Object[][] を表現しています。
メソッドの型指定子
メソッドの型指定子は、以下の様な形式で記述されます。
(引数リスト)返り値の型
引数リストは引数の型の型指定子を順に並べたものです。
スペースやカンマなどの区切り文字は入りません。
引数の型には void を除くプリミティブ型、オブジェクト型、及び配列型の型指定子が利用できます。
返り値の型は void を含むプリミティブ型、オブジェクト型、及び配列型の型指定子です。
例えば、int と String を引数に取り、Object 配列を返すメソッドの型指定子は以下のようになります。
(ILjava/lang/String;)[Ljava/lang/Object;
引数リストの長さは最大で 255 までで、それ以上長い引数リストを持つメソッドは不正なメソッドとなります。
ただし、long 及び double は引数 2 つ分と数えます。
これは long, double がほかの型と異なり 8 バイトであるためです。
Java ではオブジェクトは 4 バイトの参照(アドレス)で渡されるので、long, double のみ倍のサイズとなります。
(注: Java は参照渡しだ!と言っている人がいますがそれは誤りです。この渡し方は参照の値渡しと呼びます)
そのため、この long, double の特別扱いには定数プールの時と異なり意味があります。
あとがき
Java クラスファイルの構成について、残るは属性(attribute)のみです。
と言っても、属性の説明だけで他の部分の説明の何倍にもなりますが。
ここに書いた情報は全てJavaの仮想マシン仕様書に書いてあります。
詳しく知りたい方はそちらを読みましょう。