2017-04-15 9 views
7

以下のコードとEclipse 4.5.0の出力を考慮してください。& javac(1.8)。Javaが型消去プロセスで「型キャスト」を挿入する場所を決定する方法

私はそれが実行時の型消去によるものだと知っていますが、なぜ2番目のデータもまだList of Integerとして宣言されていても、私はjavapでチェックしました。checkcastバイトコードは3番目の出力にのみ挿入されます。

私の質問は以下のとおりです。それはバグ

  1. のですか?

  2. 「キャスト」の挿入先をjavacが決定する方法は?

    public static void main(String[] args){ 
    List<String> a = Arrays.asList("abc","def"); 
    List<Integer> b = (List<Integer>)(List<?>)a; 
    System.out.println(b.size()); --output 2 
    System.out.println(b.get(1)); ---output "def" 
    System.out.println(b.get(1).getClass()); --error in type cast 
    

EDITは、私の場合と非常に似て以下の答えとWhen is generic return value of function casted after type erasure?をチェック。 この回答をWhat is meant by "the erasure of the static type of the expression on which it is called" in the getClass() docs?から追加すると、「キャスト」ルールがはっきりします。

コンパイラは、キャストを挿入する場所を決定し、型の安全を確保できます。

私の最初のケースは、とにかくintを返すので、問題ありません。

println expectオブジェクト以降、2番目のケースは正常です。型の安全性を確保するためにキャストは必要ありません。

getClass()はJLSに従ってb.get(1)の静的型であるClassを返すことが予想されるため、Thridのケースはありません。したがって、キャストが挿入され、型キャストエラーが発生します。

@newacctは「どちらの方法でも決定するためにコンパイラに頼るべきではありません」と述べています(代替選択肢があり、型の安全性を保証する場合は2番目のケースです)。最後の例で

+0

#2のタイプのために動作します。オブジェクトではないことを忘れてしまったので、Integerであるということについてあなたが「嘘をついた」ことは、もはや気にしていません。なぜ#3が失敗するのか分かりません。 – Novaterata

+0

@Novaterata、私はそうは思わない。単にパラメータ変数を削除するだけでなく、「必要なキャスト」を挿入することもできます。したがって、3番目にはキャストが挿入されているため、実行時に型チェックに失敗する((Integer)b.get(1))。getClass()となります。 – Keith

+0

#2と#3が印刷文 – Novaterata

答えて

0

Class clazz = ((Integer)b.get(1)).getClass(); 

ひいては第二線

System.out.println(b.get(1)); 

が整数に割り当てず、従って鋳造習慣が起こる例外は、次のように、キャストが、起こります失敗したことを確認するには整数に割り当てます。

Integer x = b.get(1); //fails 
+0

なぜ2番目が成功するのですか? – Keith

+0

@Keith編集を確認する –

+3

'Object'のメソッドであるため、' getClass'を呼び出すために 'Integer'にキャストする必要はありません。では、なぜ3番目のケースにキャストがありますか? –

関連する問題