Java VMとコンパイラ、型システム

あー、Javaわからん。型システムもよくわからん。普段そこまで意識することは無いのだが、Javaを使っているとたまに型でハマることがある。いまからJava仮想マシン仕様を読んで読み取れたことと適当な推測をメモしておくので、間違っていたらどなたかコメントして欲しい。
Java言語の仕様とVMの仕様がごっちゃになっているので、そのあたりを整理したい。

Java仮想マシン仕様から読み取れたこと

型はコンパイル時の概念である

変数や式には型がある。しかしオブジェクトや配列には型が無く、その代わりにクラスに属している。

Java仮想マシン仕様 第2版 P14

型とは

プログラミング言語Javaは強く片付けされた(strongly typed)言語、つまりすべての変数や式の型がコンパイル時に決定出来る言語である。型とは、変数が保持する値、あるいは式が生成する値を制限し、それらの値に対する演算を制限し、また操作の意味を決定するものである。

Java仮想マシン仕様 第2版 P6

変数とは

変数(variable)とは、記憶領域のことであり、コンパイル時の型(compile-time type)と呼ばれるプリミティブ型($2.4.1)や参照型($2.4.6)といった型に対応づけられている。変数には、常にその型に対して代入互換性($2.6.7)のある値が保持される。プリミティブがたの変数には、常にそのプリミティブ型の値が保持される。参照型の変数には、null参照、あるいはその変数の型に対して代入互換性($2.6.7)のあるクラスの任意のオブジェクトへの参照を保持させることができる

Java仮想マシン仕様 第2版 P11

推測

クラスHogeの変数に互換性の無いクラスFugaのオブジェクトを代入するようなコードをJavaで書き、Javaコンパイラでコンパイルするとコンパイルエラーになる。これは単にJavaの言語仕様上そうなっており、Java VMの仕様では無い。上記のような代入をするバイトコードを手で書けば正しいクラスファイルとしてJava VM上で動かせるはず(Class Cast Exceptionは出るが)。

public class Test {
    public Hoge hoge = new Hoge();
    ...
}

上記のソースコードJavaコンパイラでコンパイルしたとき、クラスファイル内で変数hogeは単なる参照型(クラス型)のhogeとして宣言されている。そして

public class Test {
    Hoge hoge = new Fuga();
    ...
}

上記のソースコードJavaコンパイラでコンパイルするとき、HogeがFugaのスーパークラスであるかどうかはJavaコンパイラがチェックしてコンパイルエラーを出す。この上記ソースコードと等価な処理をバイトコードで上記を代入するようなコードを書く事はできるが、実行時にJava VMがClassCastExceptionをスローする。


型システム入門 −プログラミング言語と型の理論−

型システム入門 −プログラミング言語と型の理論−

  • 作者: Benjamin C. Pierce,住井英二郎,遠藤侑介,酒井政裕,今井敬吾,黒木裕介,今井宜洋,才川隆文,今井健男
  • 出版社/メーカー: オーム社
  • 発売日: 2013/03/26
  • メディア: 単行本(ソフトカバー)
  • クリック: 68回
  • この商品を含むブログ (7件) を見る

これでも買うか...。