31

これは、Java仕様の欠点に関連して、別の質問への回答で見ました。

さらに欠点があり、これは微妙なトピックです。これをチェックしてください:

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);
     }
}

ここでは、コンパイラが自動ボクシングよりも拡張を選択するため、「long」が出力されます(自分でチェックしていません)。自動ボクシングを使用するときは注意するか、まったく使用しないでください。

これは実際にはオートボクシングではなく拡大の例であると確信していますか、それともまったく別のものですか?

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

hello(long x)

hello(Long x)

出力は「整数」を出力します

ここで実際に何が起こっているのですか?私はJava用のコンパイラ/バイトコードインタプリタについて何も知りません...

4

3 に答える 3

16

最初のケースでは、拡大変換が発生しています。これは、コンパイルされたクラスで "javap" ユーティリティ プログラム (JDK に付属) を実行すると表示されます。

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

}

明らかに、拡大する Integer-To-Long バイトコード命令のニーモニックである I2L が表示されます。こちらのリファレンスを参照してください

それ以外の場合は、"long x" をオブジェクトの "Long x" シグネチャに置き換えると、メイン メソッドに次のコードが含まれます。

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

}

コンパイラが命令 Integer.valueOf(int) を作成して、プリミティブをラッパー内にボックス化したことがわかります。

于 2008-08-07T18:18:34.897 に答える
5

はい、そうです。テストで試してみてください。「長い」が印刷されます。Javaは、整数への自動ボックス化を選択する前にintをlongに拡張することを選択するため、拡張されます。そのため、hello(long)メソッドが呼び出されるように選択されます。

編集:参照されている元の投稿

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

于 2008-08-07T16:36:25.447 に答える
3

この例のもう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);
}

Listである実行時型を使用せず、Collectionであるコンパイル時型を使用するため、「Collection」を出力します。

JLSのいくつかのコーナーケースに目を向けたEffectiveJavaをお読みになることをお勧めします。

于 2008-08-07T19:02:29.630 に答える