2013-08-07 9 views
26

最後に、ジェネリックを少し試してみました。私は、コードのこの部分を思い付いた:Java:ジェネリックの実験

public class Test { 

    static <T> void f(T x) { 
     x = (T) (Integer) 1234; 
     System.out.println(x); 
    } 

    public static void main(String[] args) { 
     f("a"); 
     f(1); 
     f('a'); 
     f(1.5); 
     f(new LinkedList<String>()); 
     f(new HashMap<String, String>()); 
    } 
} 

私はこれを実行し、この出力ました:例外なく

1234 
1234 
1234 
1234 
1234 
1234 

を!どのように可能ですか?

+0

は注意してください - あなたは尋ねるに危険なほど近くに迷走している:「なぜジェネリック医薬品は、C++のテンプレートのように動作しないのですか?」 –

答えて

36

それは(多くはちょうどこの期間のためのgoogle、これについて書かれている)ので、type erasureのです。バイトコードへfをコンパイルした後の方法は、次のようになります。

static void f(Object x) { 
    x = (Object) (Integer) 1234; 
    System.out.println(x); 
} 

のでSystem.out.printlnはちょうどオブジェクトxtoStringメソッドを呼び出します - そして、あなたのケースではInteger.toString()です。

+1

thatsすてきな答え:) –

3

タイプ消去のためです。 Oracle's documentationから:

ジェネリック医薬品は、コンパイル時にタイトなタイプ チェックを提供し、一般的なプログラミングをサポートするために、Java言語に導入されました。 にジェネリックを実装し、Javaコンパイラはに型消去を適用します。

  • 型パラメータが無制限であれば、その範囲や オブジェクトとジェネリック型のすべての型パラメータを交換してください。したがって、生成されたバイトコード には、通常のクラス、インタフェース、およびメソッドのみが含まれます。型の安全性を維持するために必要に応じて

  • 挿入タイプがキャスト。

  • は、拡張されたジェネリック型で多型を維持するためのブリッジメソッドを生成します。

タイプ消去は、パラメータ化された タイプに対して新しいクラスが作成されないようにします。その結果、ジェネリックスにはランタイムオーバーヘッドが発生しません。

+3

外部リソースの言葉をコピーするときは、必ず元の言葉を正しく引用してリンクしてください。 –