この記事の目的
簡単なコード例から、javaのジェネリクス型における型消去(Type Erasure)という仕組みを見ていきます。
ちょっと変なコードがある→面白そう と感じてもらえればうれしいです。
この記事では、型消去は簡単な解説にとどめます。
詳しい説明は、他の記事や公式ドキュメントに譲ります。
参考:java 公式ドキュメント(Type Erasure)
https://docs.oracle.com/javase/tutorial/java/generics/erasure.html
まずはコード
public class Container<V>{
V value;
public void setValue(Object value){
this.value=(V)value;
}
}
public class Main{
public static void main(String... arg){
Container<String> con=new Container<>();
Integer i=0;
con.setValue(i);
}
}
おかしなコードですね
まず、setValue(value)の引数型がObjectです。ここは、Vを引数の型にしたほうがよいですが、コンパイルは通りそうです。
つぎに、con.setValue(i)の部分を見てください。Stringをvalueとして持つconにInteger型の変数iを入れようとしていてまずいですね。
では、コンパイルが通るか・実行できるかという観点ではどうなのでしょうか?
このコードは実行できるのか?
次の二つの観点で見ると、このコードはどうでしょうか。
- コンパイルは通りますか?
- それとも実行時エラーが投げられる?(
ClassCastException?)
答えは...
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
実は正常に動きます
実は、全く問題なく動きます。
※コンパイル・実行はできますが、this.value=(V)value;の部分でwarningは出ます。
例えば、次のようなprint()を実装しても、ちゃんと動きます:
//Containerクラスの中
public void print(){
System.out.println("value is "+this.value);
}
//con.setValue(0)の場合
value is 0
//con.setValue("tmp")の場合
value is tmp
仕組みを解説
タイトルの通り、型消去(Type Erasure)という仕組みが肝です。
これは、javaにおけるジェネリクス型における仕組みです。
よくあるジェネリクス型の説明
ジェネリクス型によって、
Container<Object> Container<Integer> Container<String>
のように、複数のクラスがコンパイラで作られる
という説明がよくあります。
が、これは正確には正しくありません。
実際には
コンパイルの時点で型の情報は消え、実際には
Container<Object>
というクラスが使いまわされます。
これを型消去(Type Erasure)といいます。
つまり、
Container<String> conという変数は、コンパイル後(実行時)にはContainer<Object>となっているわけです。
最初のコードを見返すと
前述の通りコンパイルは通ります。つまり、conはContainer<Object>の変数として扱われます。
最初のコードは、次のように解釈できます。
Container<String> con=new Container<>();
//実行時には、Container<Object>として扱われる
//con.valueの型もObject
Integer i=0;
con.setValue(i);
//setValue(i)の中では
//con.value=(Object)value; が実行される
実行時には、コメントで書いたような処理になります。
型消去の仕組みのせいで、最初に示したコードも普通に動くのです。
まとめ
本記事では、型消去(Type Erasure)の次の2つ特徴を利用しました。
- コンパイル後に型の情報は消える
-
Container<Object>というクラスが使いまわされる
これによって、最初のコードは動くわけです。
ちょっとでも面白いな、不思議だな、と思っていただけましたか?
参考
java 公式ドキュメント
https://docs.oracle.com/javase/tutorial/java/generics/erasure.html
改訂2版 パーフェクトJava 井上 誠一郎・永井 雅人 (著) 技術評論社