5

この質問と、SCJP 1.6 セルフテストの質問に対する回答の説明を理解するのに苦労しています。問題は次のとおりです。

class A { }
class B extends A { }
public class ComingThru {
    static String s = "-";
    public static void main(String[] args) {
        A[] aa = new A[2];
        B[] ba = new B[2];
        sifter(aa);
        sifter(ba);
        sifter(7);
        System.out.println(s);
    }
    static void sifter(A[]... a2) { s += "1"; }
    static void sifter(B[]... b1) { s += "2"; }
    static void sifter(B[] b1) { s += "3"; }
    static void sifter(Object o) { s += "4"; }
}

結果は?答えは -434 ですが、本書の説明が気になります。これは、この章の前半で概念が説明された方法とは大きく異なります。

「一般に、オーバーロードされた var-args メソッドは最後に選択されます。配列はオブジェクトであることを思い出してください。最後に、int を Integer にボックス化し、オブジェクトに「拡張」できます。」

それを分割して、誰かがその説明をさらに定義してもらえますか?

  1. 一般に、オーバーロードされた var-args メソッドは最後に選択されます。
  2. 配列はオブジェクトです (私は実際にそれを理解していますが、なぜそれがこの質問に関連しているのでしょうか)。
  3. int は Integer にボックス化してから Object に「拡張」できます。

ありがとう!

4

2 に答える 2

6

この本は、最初の 2 つのオーバーロードが選択されない理由を説明しようとしています。なぜなら、var-args マーカー...によって、考えられる他のすべてのオーバーロードが失敗した場合にのみ、これらのオーバーロードが使用されるからです。この場合、これは起こりません。「Remember」で始まる 2 つの文は、なぜそれが起こらないのか、最初と最後のケース (2 番目のケースと 3 番目のオーバーロードとの一致) に他の可能なオーバーロードが存在する理由を説明しています。 sifter は明らかです): 配列はオブジェクトであり、int はボックス化してオブジェクトに拡張できるため、4 番目のオーバーロードは sifter への呼び出しの最初と最後のものに一致します。

于 2009-07-15T03:45:45.293 に答える
4
  1. どちらのメソッドを呼び出すかを決定しようとするとき、両方のメソッドが (多かれ少なかれ) 同じクラスに属している場合、コンパイラは最初に非可変引数メソッド (例 ) を探してから、可変引数メソッド (例sifter(Object)) を検討します。sifter(A[]...)

  2. 配列は であるためObject、 の呼び出しはsifter(aa)に一致sifter(Object)するため、 も考慮しませんsifter(A[]...)

  3. Java 5 以降、コンパイラはプリミティブを「ボックス化」する場合があります。つまり、プリミティブ値 (例: int) を対応する値 (Object例: ) に変換しますInteger。したがってsifter(6)、コンパイラは を に変換するint 6ためInteger 6、メソッドと一致しsifter(Object)ます。

于 2009-07-15T03:51:54.283 に答える