6

重複の可能性:
varargs とオーバーロードのバグ?

誰かがこれがどのように機能するかを説明できますか:

class Vararg {
    static void vararg(int... x) {
        System.out.println("Integer..."); 
    }

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

    public static void main(String [] args) {
        int s = 0;
        vararg(s,s);
    }
}

コンパイル時エラーを取得する

class Vararg {
    static void vararg(Integer... x) {
        System.out.println("Integer..."); 
    }

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

    public static void main(String [] args) {
        int s = 0;
        vararg(s,s);
    }
}

また、コンパイル時エラーが発生します。varargs でオーバーロードを使用するときのメカニズムは何ですか? varargs メソッドのオーバーロードのバグですか?

4

2 に答える 2

16

実際には、どの方法が適用可能かを判断するために、コンパイラはいくつかの手順を実行します

  • 最初に、ボクシング/アンボクシングまたは可変引数を使用せずにメソッドを見つけようとしています
  • 2番目にメソッドを見つけようとし、ボックス化/ボックス化解除を許可しますが、可変引数は使用しません
  • 3 番目は、ボクシング、アンボクシング、可変引数を許可します

あなたの場合、3番目のステップはすべての方法に適用できます。

次に、コンパイラは、どのメソッドが適用可能かを判断し、あるメソッドが別のメソッドよりも具体的かどうかを判断します。詳細なルールはJLS 15.12.2.4にあります。要するに、型を見て、一方が他方より具体的であるかどうかをチェックします (つまり、一方の型が他方の参照のサブクラスであるか、プリミティブの型が別の型よりも狭い)。

あなたの場合:

  • 例 1 では、両方の方法が適用可能ですが、intより具体的な方法が選択されlongています。vararg(int...)
  • 例 2 では、 (一方が参照で、もう一方がプリミティブである) との特異性関係Integerがないため、両方が最大限に特異的であり、コンパイル エラーにつながるあいまいさが存在します。long

編集

最初の例はコンパイルされますが、2番目の例はコンパイルされないと言っていると思いました(これは予想される動作です)。どちらもコンパイルしないと言っているようですが、その場合はjavac、Java 7 で修正された のバージョンのバグが原因である可能性があります。詳細については、リリース ノートの「最も具体的な Varargs メソッドの選択の変更」というセクションを参照してください。 .

于 2013-02-05T13:37:20.550 に答える
0

vararg(type... var) メソッドで int 値を送信し、オーバーロードされたメソッドには 1 つの Integer と 1 つの long が含まれているため、int 値は自動的に long にキャストされるため、あいまいさが生じます。オーバーロードされたメソッドで異なるパラメーター タイプを使用します。

class Vararg {
static void vararg(Integer... x) {
    System.out.println("Integer..."); 
}

static void vararg(String... x) {
    System.out.println("String..."); 
}

public static void main(String [] args) {
    int s = 0;
    vararg(s,s);
}

}

于 2013-02-05T13:40:17.327 に答える