この記事の目的
簡単なコード例から、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 井上 誠一郎・永井 雅人 (著) 技術評論社