5

私は問題なくコンパイルできる 2 つのコンストラクターを持っていますが、Java があいまいさの可能性について不平を言うことを期待しています。

public Foo(int id, Bar bar, String name, String description){
}

public Foo(int id, Bar bar, String... values){
}

何を与える?

4

2 に答える 2

7

Java では、これらのメソッドの存在が許可されています。これは、両方が適用される場合にどちらが呼び出されるかに関する規則があるためです。具体的には、固定アリティ方式 ( なし...) が可変アリティ方式 ( あり...) よりも選択されます。

JLSのセクション 15.12.2では、選択する方法を決定する際に次のように述べています。

最初のフェーズ (§15.12.2.2) では、ボックス化またはボックス化解除の変換、または可変アリティ メソッド呼び出しの使用を許可せずに、オーバーロードの解決を実行します。このフェーズで適用可能なメソッドが見つからない場合、処理は 2 番目のフェーズに進みます。

これにより、Java SE 5.0 より前の Java プログラミング言語で有効だった呼び出しが、可変アリティ メソッド、暗黙的なボックス化および/またはボックス化解除の導入の結果として、あいまいと見なされないことが保証されます。ただし、可変アリティ メソッド (§8.4.1) の宣言は、特定のメソッド メソッド呼び出し式に対して選択されたメソッドを変更する可能性があります。これは、可変アリティ メソッドが最初のフェーズで固定アリティ メソッドとして扱われるためです。たとえば、すでに m(Object) を宣言しているクラスで m(Object...) を宣言すると、m(Object[] のように、一部の呼び出し式 (m(null) など) で m(Object) が選択されなくなります。 ) はより具体的です。

2 番目のフェーズ (§15.12.2.3) では、ボックス化とボックス化解除を許可しながらオーバーロードの解決を実行しますが、可変アリティ メソッドの呼び出しは引き続き使用できません。この段階で適用可能なメソッドが見つからない場合、処理は第 3 段階に進みます。

これにより、メソッドが固定アリティ メソッドの呼び出しによって適用される場合、可変アリティ メソッドの呼び出しによってメソッドが選択されることはありません。

第 3 フェーズ (§15.12.2.4) では、オーバーロードを可変アリティ メソッド、ボックス化、およびボックス化解除と組み合わせることができます。

(私のものを強調)

コード例:

class Bar{}

public class Foo{
   public static void main (String [] args){
      Foo main = new Foo(1, new Bar(), "name", "description");
      Foo main2 = new Foo(2, new Bar(), "name");
      Foo main3 = new Foo(3, new Bar(), "name", "description", "otherValues");
      Foo main4 = new Foo(4, new Bar());    
   }

   public Foo(int id, Bar bar, String name, String description) {
      System.out.println("name and description!");
   }

   public Foo(int id, Bar bar, String... values) {
      System.out.println("values!");
   }
}

これは出力します:

name and description!
values!
values!
values!

...可能であれば、Javaが固定アリティ方式を選択することを示します。

于 2013-10-14T18:13:21.640 に答える