2

私は2つの関数を作成したいと思います

long min(long...);
int min(int...);

しかし、2番目の、つまりmin(1, 5)1つを呼び出そうとすると、あいまいなメソッド呼び出しが発生します

名前を変更する以外の回避策はありますか?

4

4 に答える 4

6

既知のバグです

あなたが説明する動作は、Java 7 で修正されたバグです。詳細については、リリース ノートの「最も具体的な Varargs メソッドの選択の変更」というセクションを参照してください。

コンパイルする理由

可変アリティは、最も具体的な方法を決定する際に最後に来ます。複数ある場合にどの vararg メソッドが適用されるかを決定するルールは、JLS 15.12.2.4で定義されています。

次のいずれかの場合、m という名前の可変アリティ メンバ メソッドは、同じ名前の別の可変アリティ メンバ メソッドよりも具体的
です

  • 最初のメソッドのパラメーターの型は、U1、...、Uk-1、Uk[] です。
  • もう一方のメソッドのパラメータの型は、T1、...、Tn-1、Tn[] です。
  • 1 から n までのすべての j に対して、Uj <: Tj

あなたの場合、k = n、およびU1[] = int[]その逆T1[] = long[]かどうかの決定を下すことができます。int <: long

つまり、考慮される型はint[]vslong[]ではなくintvslongです。そのint <: longため、int...メソッドを選択してコンパイルする必要があります。

結論:

このコードは、Java 7 では正常にコンパイルされるはずですが、Java 5 または 6 ではコンパイルされません。以下のコードはint、Java 7 で出力されます。

public class Test1 {
    public static void main(String[] args) {
        new Test1().m(1, 2);
    }
    int m(int... i) {
        System.out.println("int");
        return 0;
    }
    long m(long... i) {
        System.out.println("long");
        return 0;
    }
}
于 2012-11-23T07:04:02.413 に答える
1

これを試して

public class Test {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new Test().m(100L,512L);
        new Test().m(100,512);
    }

    int m(int... i) {
        System.out.println("int");
        return 0;
    }

    long m(long... i) {
        System.out.println("long");
        return 0;
    }
}
于 2012-11-23T09:24:58.563 に答える
1

問題は、これらのメソッドを で呼び出すと、使用したようにintegerどのメソッドも引数に完全に一致しないことですvar-args。また、どちらもコンマで区切られた値を引数としてvar-args取ることができます。intしたがって、ambiguous methodエラー。

オーバーロードされたメソッドを呼び出すときCompilerは、最初のメソッドを選択しexact matchます。次に、nearest typeキャストします。

現在、var-argsは単なる であるため、コンパイラは値arrayを渡すときに使用する配列を決定できません。として、どちらの配列もまたはintegerと見なすことはできません。したがって、呼び出し可能なメソッドの両方が必要です。exact matchnearest conversion

method invocationの場合には、さらに多くのルールがありますOverloading。からそれらを学ぶことができますJava Language Specification


@assylias answerのように、この問題は Java 7 で修正されました。ただし、Java バージョン < 7 では機能しません。

于 2012-11-23T06:40:49.397 に答える
0

これらのメソッド シグネチャは一意であり、有効なメソッド オーバーロードです。

問題はメソッド呼び出しの引数にあるはずです。私の推測では、次のようなリテラルでメソッドを呼び出していると思います。

min(100) 

100 は整数リテラルであるため、これは好ましくありませんが、自動的に long に変換されます。

長いリテラルの最後に L を使用してメソッド呼び出しを明確にすると、問題が解決するはずです。

min(100L)

また、Java Object Integer と Long を使用して呼び出しを明示的に行い、プリミティブ型への変換を自動ボクシングに任せることもできます。

min(new Long(100))
min(new Integer(100))
于 2012-11-23T06:37:46.857 に答える