これは、サードパーティのライブラリAPIからの実際の例ですが、簡略化されています。
Oracle JDK 8u72でコンパイル
次の2つの方法を検討してください。
<X extends CharSequence> X getCharSequence() {
return (X) "hello";
}
<X extends String> X getString() {
return (X) "hello";
}
どちらも「チェックされていないキャスト」警告を報告します-理由はわかります。私を困惑させるのは、なぜ私が電話できるのか
Integer x = getCharSequence();
そしてそれはコンパイルしますか?コンパイラは、Integer
がを実装していないことを知っている必要がありますCharSequence
。への呼び出し
Integer y = getString();
エラーを出します(予想通り)
incompatible types: inference variable X has incompatible upper bounds java.lang.Integer,java.lang.String
この動作が有効と見なされる理由を誰かが説明できますか?それはどのように役立ちますか?
クライアントは、この呼び出しが安全でないことを認識していません-クライアントのコードは警告なしでコンパイルされます。コンパイルがそのことを警告しない、またはエラーを発行しないのはなぜですか?
また、この例との違いは次のとおりです。
<X extends CharSequence> void doCharSequence(List<X> l) {
}
List<CharSequence> chsL = new ArrayList<>();
doCharSequence(chsL); // compiles
List<Integer> intL = new ArrayList<>();
doCharSequence(intL); // error
渡そうとするList<Integer>
と、予想通りエラーが発生します。
method doCharSequence in class generic.GenericTest cannot be applied to given types; required: java.util.List<X> found: java.util.List<java.lang.Integer> reason: inference variable X has incompatible bounds equality constraints: java.lang.Integer upper bounds: java.lang.CharSequence
それがエラーとして報告された場合、なぜそうでInteger x = getCharSequence();
はないのですか?
Integer x = getCharSequence();
はコンパイルされますが、RHSでのキャストはコンパイルにInteger x = (Integer) getCharSequence();
失敗します