22

非常に興味深いJavaのトリックについて知りました。

void method1(Integer... a){
}

したがって、このメソッドには必要な数の整数を指定できます。

今、私がこのような同様の(オーバーロードされた)メソッドを持っている場合:

void method1(int a, int b){

}

次の行を実行すると、どのメソッドが実行されますか。

method1(1, 2);

さて、私はそれをさまざまなメソッド命令でテストするだけで非常に簡単に見つけることができましたが、「オーバーロード」メソッドの「ルール」について考えるとき、コンパイラが認識できるように、すべてのオーバーロードされたメソッドが同一でなければならないことを確認する必要があります正確にどれを使用するか。

私の意見では、コンパイラが混乱しているため、上記のコードは機能しないはずです。しかし、私がそれを試してみると、それはうまくいきます。

だから..誰かがこれについてもう少し背景情報を知っていますか?

4

5 に答える 5

30

呼び出す必要のあるメソッドを決定するために、コンパイラーは、JLS#5.3およびJLS#15.12.2で詳しく説明されているように、次のリストを調べます。

  • ID変換(§5.1.1)=>method1(int a, int b)
  • 拡大するプリミティブ変換(§5.1.2)
  • 拡大参照変換(§5.1.5)
  • ボクシング変換(§5.1.7)とそれに続く拡張参照変換 ==>method1(Integer... a)
  • 開開変換(§5.1.8)の後に、オプションで拡張プリミティブ変換が続きます。

あなたの場合、最初のポイントが適用され、method1(int, int)呼び出されます。

(より正確には、メソッドはvaragを使用し、単純なボクシング変換よりも優先度が低くなります。つまり、階層内でmethod1(Integer a, Integer b)前に存在する場合)method1(Integer... a)

なんでそうなの?15.12.2のコメントはヒントを与えます:

これにより、Java SE 5.0より前のJavaプログラミング言語で有効だった呼び出しが、可変アリティメソッドの導入、暗黙的なボックス化および/またはアンボックス化の結果としてあいまいであると見なされないことが保証されます。

于 2012-08-03T21:33:34.657 に答える
4

2番目の方法が優先されます。Java言語仕様(pdf)によると、

最初のフェーズ(§15.12.2.2)は、ボックス化またはボックス化解除の変換、または可変アリティメソッド呼び出しの使用を許可せずに過負荷解決を実行します。

この段階で適切な方法が見つかった場合、その方法が優先されます。それ以上の検索は実行されません。あなたの場合、それはたまたま2番目の方法です。最初の方法は、ボクシングも必要とする可変アリティ法だからです。

于 2012-08-03T21:35:59.180 に答える
2

method1(int a、int b)が呼び出されます。これについてバイトコードをチェックしたばかりです-これInteger... aは実際にはですInteger[] a 詳細な変換についてはこれらの割り当て変換をチェックしてください

于 2012-08-03T21:39:46.420 に答える
2

私は半分推測していますが、thinksteepが言ったように、Integer...実際には配列として扱われIntegerます。つまり、メソッド呼び出しは、最初のメソッドと一致させるために2つの強制を実行する必要があります(intsをIntegersにボックス化し、引数リストを単に2つの異なる引数ではなく配列)。一方、2番目の方法と一致させるために強制は必要ありません。

OK、私がこれを入力している間に、他の何人かが私が提供したよりも具体的にJLSをすでに引用しているのを見ることができます。

于 2012-08-03T21:40:51.973 に答える
1

varargsの優先度は最も低くなります。他に一致するメソッドが見つからない場合は、それだけが呼び出されます。これは、 SWITCHの場合のデフォルトの場合とまったく同じです。

于 2016-05-27T04:21:14.023 に答える