2011-06-29 11 views
2

私はThinking in java、Genericsを読んでいます。逆アセンブルコード線18によれば、一例では(段落「境界で動作」で)Javaジェネリックで実行時にString型の戻り値のみがチェックされるのはなぜですか?

public class GenericHolder<T> { 
    private T obj; 
    public void set(T obj) { this.obj = obj; } 
    public T get() { return obj; } 
    public static void main(String[] args) { 
     GenericHolder<String> holder = 
     new GenericHolder<String>(); 
     holder.set("Item"); 
     String s = holder.get(); 
    } 
} ///:~ 


public void set(java.lang.Object); 
    0: aload_0 
    1: aload_1 
    2: putfield #2; //Field obj:Object; 
    5: return 
public java.lang.Object get(); 
    0: aload_0 
    1: getfield #2; //Field obj:Object; 
    4: areturn 
public static void main(java.lang.String[]); 
    470 Thinking in Java Bruce Eckel 
    0: new #3; //class GenericHolder 
    3: dup 
    4: invokespecial #4; //Method "<init>":()V 
    7: astore_1 
    8: aload_1 
    9: ldC#5; //String Item 
    11: invokevirtual #6; //Method set:(Object;)V 
    14: aload_1 
    15: invokevirtual #7; //Method get:()Object; 
    18: checkcast #8; //class java/lang/String 
    21: astore_2 
    22: return 

、コンパイラはcheckcastコードを付加します。私はジェネリックのために常にこのようなチェックキャストになるかどうかを知りたい。 StringをIntegerに置き換えてもう一度やり直しましたが、最後にチェックキャストコードが見つかりませんでした。 Object型も同様です。

誰かがそれを説明できますか? JavaのStringは特別なオブジェクトですか?

+0

オブジェクトの場合、オブジェクトにキャストすることができるので、キャストは必要ありません。 –

答えて

5

私は文字列を整数に交換して、再度試してみましたが、私は最後のcheckcastコードを見つけられませんでした。

は、私にとってはIntegerにもcheckcastを生成します。

0: new #3; //class GenericHolder 
    3: dup 
    4: invokespecial #4; //Method GenericHolder."<init>":()V 
    7: astore_1 
    8: aload_1 
    9: iconst_5 
10: invokestatic #5; //Method java/lang/Integer.valueOf:(I) 
13: invokevirtual #6; //Method GenericHolder.set:(Ljava/lang/Object;)V 
16: aload_1 
17: invokevirtual #7; //Method GenericHolder.get:()Ljava/lang/Object; 
20: checkcast #8; //class java/lang/Integer 
23: astore_2 
24: return 

あなたが見ることができるように、get方法はLjava/lang/Object;は、checkcastが返さObjectがあることを確認することですつまり、署名を持っています確かにIntegerです。


編集:あなたがコメントとして投稿のコードで:あなたはObject受け入れPrintStream.printに返された値を渡す

0: getstatiC#2; //Field java/lang/System.out:Ljava/io/PrintStream; 
3: new #3; //class b/TestG 
6: dup 
7: new #4; //class java/lang/Integer 
10: dup 
11: iconst_2 
12: invokespecial #5; //Method java/lang/Integer."<init>":(I)V 
15: invokespecial #6; //Method b/TestG."<init>":(Ljava/lang/Object;)V 
18: invokevirtual #7; //Method b/TestG.getT:()Ljava/lang/Object; 
21: invokevirtual #8; //Method java/io/PrintStream.print:(Ljava/lang/Objec t;)V 
24: return 

。したがって、戻り値をキャストする必要はありません。 (checkcast java.lang.Objectは常に通ります!)

+0

7:新しい#4; //クラスjava/lang /整数 10:dup 11:iconst_2 12:invokespecial#5; //メソッドjava/lang/Integer。 "":(I)V 15:invokespecial#6; //メソッドb/TestG。 "":(Ljava/lang/Object;)V 18:invokevirtual#7; //メソッドb/TestG.getT :()Ljava/lang/Object; 21:invokevirtual#8; //メソッドjava/io/PrintStream.print:(Ljava/lang/Objec t;)V 24:return javap -c filenameを使用していますが、そのようなコードはありませんか? – x4snowman

+0

答えを更新しました。 – aioobe

+0

ありがとうございました..私はJavaに新しいです、ジェネリックはとても私に混乱しているようです。 – x4snowman

関連する問題