2016-07-18 9 views
5

私はジェネリッククラスのパーセルとジェネリックメソッドのデリバリーを以下のコードに示しているとします。このメソッドは、メソッド内で型パラメータIntegerが割り当てられたxを出力して返します。パラメータを入力しても役割はありませんか?

public class Parcel<T> { 
    public <X> X deliver(){ 
     X x = (X) new Integer(100); 
     System.out.println(x); 
     return x; 
    } 
} 

メインの内部では、タイプパラメータParcelを渡してメソッドdeliverを呼び出します。しかし、まだ100をプリントしています。

これは、print行に渡された型引数Parcelが何の役割も果たさないことを意味し、ここでは例外が予想されます。どのように機能するのですか?

+5

あなたは 'java.lang.Object'にバインドしているためです。 'X'は上限が' java.lang.Object'であると仮定して特定の型に束縛されていないので、 'ClassCastException'はありません。 'deliver'を呼び出し、' java.lang.Object'、 'java.lang.Number'、および' java.lang以外の型を持つ変数/フィールド/パラメータに結果をキャストすると、1つを取得します。整数 'である。また、 'println(Object)'を呼び出すのでコードが失敗することはありません。それを 'parcel 'に変更した場合。 deliver() 'の場合、コンパイラはjava.lang.Integerをjava.lang.Stringにキャストできない' println(String) 'を使用します –

+1

また、' '制約をmoreに変更することができますコンパイラは 'deliver()'メソッドでコンクリート型キャストを使用します。 'X extends String>は' ClassCastException'を返します。 'X'は' java.lang.String'に置き換えられているため、 'X x =(X)(Object)new Integer(100);'ここに。 –

答えて

1

あなたが観察したことは、type erasureと呼ばれています。一般的なパラメータは、型の正確さを保証するためにコンパイラによって使用され、実行時には存在しません。

は、実は私の元の答えは時折このParcel実装

public class Parcel<T> { 
    public T deliver(){ 
     T x = (T) new Integer(100); 
     System.out.println(x); 
     return x; 
    } 
} 

のためだった

List<Integer> list = new ArrayList<>(); 
list.append(""); // produces compiler error 

// just drop that "useless" generic argument 
List erased = (List) list; 
erased.append(""); // works fine 

EDITしかし、重要な考え方は次のとおりです。

は、一般的には何も話していないことは、このトリックをやってからあなたを停止します<X> X deliver()と同じ:

Object parcel = parcel.<Parcel> deliver(); // erased, works ok 
Parcel parcel = parcel.<Parcel> deliver(); // java.lang.ClassCastException 
関連する問題