javaのジェネリクスで、
なぜかコンパイルエラーになってくれないものがあったので記載しておく。
ジェネリクスのコンパイル後のクラスファイルについて
@SuppressWarnings("unchecked")
static <T extends Number> T get()
{
return (T) obj;
}
↓ コンパイルされると、型情報が消えるので、クラスファイルはこうなる。
@SuppressWarnings("unchecked")
static Number get()
{
return (Number) obj;
}
コンパイルエラーになりそうで、ならないもの。
Integer i = get(); // OK
Double d = get(); // OK
String s = get(); // コンパイルエラー
List<String> strList = get(); // コンパイルエラーになってくれない
↓ コンパイルされると、こう展開される。
型情報を元に自動でキャストを挟んでいるようなもの。
Integer i = (Integer) get(); // OK
Double d = (Double) get(); // OK
String s = (String) get(); // コンパイルエラー
List<String> strList = (List<String>) get(); // コンパイルエラーになってくれない
一番したのやつは、明らかにエラーなんだけど、
なぜコンパイル時エラーが発生しないのか??
上記は、これと同等のキャスト
Number n = 1;
Integer i = (Integer) n; // OK
Double d = (Double) n; // OK
String s = (String) n; // コンパイルエラー
List<String> strList = (List<String>) n; // コンパイルエラーになってくれない
もともと、右辺がジェネリクスの場合
右辺がもともと、List<>, Set<> などのジェネリクス型の場合は、
ジェネリクス型以外のキャストはエラーになるみたいです。
あと、型パラメータのチェックもされるみたいです。
List<? extends Number> numList = new ArrayList<>();
List<Integer> intList = (List<Integer>) numList; // OK
Set<Double> doubleSet = (Set<Double>) numList; // これもコンパイルエラーにならない
Integer i = (Integer) numList; // コンパイルエラー
String s = (String) numList; // コンパイルエラー
List<String> strList = (List<String>) numList; // コンパイルエラー
おしまい
これなんで、コンパイルエラーになってくれないんだろう〜??
ジェネリクス型へのキャストの際は、原型自体のチェックはされなくて、
型パラメータのチェックだけされる。
右辺に型パラメータがないから、左辺の型パラメータともチェックできない。
という事なのかな??
だれか、わかる人教えてほしい…。