2008-08-07 25 views
26

は、私はJavaの仕様の欠点を参照して、an answer to another questionでこれを見た:これは本当に広大なオートボクシングですか?

は、より多くの欠点があり、これは微妙な話題です。外thisをチェック:コンパイラはオートボクシングの上に広げ> chosesがあるため、「長い」ここ

public class methodOverloading{ 
    public static void hello(Integer x){ 
      System.out.println("Integer"); 
    } 

    public static void hello(long x){ 
      System.out.println("long"); 
    } 

    public static void main(String[] args){ 
     int i = 5; 
     hello(i); 
    } 
} 

、(それを自分でチェックしていない)印刷されます。オートボクシングを使用する場合や、まったく使用しない場合は注意してください。

これは実際にオートバイの代わりに拡大する例であると確信していますか?

私の最初のスキャンでは、iに基づいて出力が "長く"、オブジェクトではなくプリミティブとして宣言されていることに同意します。しかし、場合には、あなたは

は本当にここで何が起こっている "整数" を印刷し

hello(Long x) 

出力に

hello(long x) 

を変えましたか?私はJavaのコンパイラ/バイトコードインタプリタについて何も知らない。

+0

確かに拡大しています。 Intは長く拡張されます。 – EJP

答えて

12

最初のケースでは、拡大変換が行われています。 (JDK/wを含む)「てjavap」ユーティリティプログラムをruninngとき、これはコンパイルされたクラスで、見ることができます明らかに

public static void main(java.lang.String[]); 
    Code: 
    0: iconst_ 5 
    1: istore_ 1 
    2: iload_ 1 
    3: i2l 
    4: invokestatic #6; //Method hello:(J)V 
    7: return 

} 

、あなたが拡大整数対のニーモニックであるI2Lを見ますロングバイトコード命令。参照番号hereを参照してください。コンパイラが作成しているので、

public static void main(java.lang.String[]); 
    Code: 
    0: iconst_ 5 
    1: istore_ 1 
    2: iload_ 1 
    3: invokestatic #6; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 
    6: invokestatic #7; //Method hello:(Ljava/lang/Integer;)V 
    9: return 

} 

あなたが見る:オブジェクトに「ロングX」を交換する

そして、他のケースでは

は、「ロングX」署名は、あなたが主な方法でこのコードを持っています(Integer.valueOf(int))、ラッパーの中のプリミティブを囲みます。

+5

古いコードは拡張に依存していて、そのコードが突然オートボックスに変わったら、Javaがオートボクシングの前に広げなければならないことは明らかです。 –

3

はい、それはテストで試してみてください。 「長い」と印刷されます。これは、JavaがIntegerにautoboxする前にintを広げようとするので、hello(long)メソッドが呼び出されるように選択されるため、広がります。

編集:the original post being referenced

さらに編集:2番目のオプションがIntegerを出力する理由は、オプションとして大きなプリミティブに「拡大」がないためです。したがって、Integerが唯一のオプションです。さらに、javaは元の型にオートボックスするだけなので、hello(Long)を残してhello(Integer)を削除すると、コンパイラエラーが発生します。

1

この例のもう1つの興味深い点は、メソッドのオーバーロードです。型の拡大とメソッドのオーバーロードの組み合わせは、コンパイラがどのメソッドを選択するか決定する必要があるためにのみ機能します。次の例を考えてみましょう:

public static void hello(Collection x){ 
    System.out.println("Collection"); 
} 

public static void hello(List x){ 
    System.out.println("List"); 
} 

public static void main(String[] args){ 
    Collection col = new ArrayList(); 
    hello(col); 
} 

それはコレクションひいては印刷物「コレクション」であるコンパイル時の型を使用して、一覧で実行時の型を使用しません。

Effective Javaを読むことをお勧めします。これにより、JLSのいくつかのコーナーケースが私の目に映りました。

関連する問題