14

2日で私はJavaで試験を受けました、そして私はこの質問への答えを理解することができません:

class ClassA {
 public String foo(Integer x , int y) {
  return "Integer, int";
 }
 public String foo(int x, Double y) {
  return "int, Double";
 }
 public String foo(Number x, Number y) {
  return "Number, Number";
 }
 public String foo(Object x, Object y) {
  return "Object, Object";
 }
 public static void main(String... args) {
  ClassA a = new ClassA();
  System.out.print(a.foo(5, 1.2f) + " ");
  System.out.println(a.foo(null, null));
 }
}

出力は何ですか?

答えは次のとおりです。

Number, Number Number, Number

私は、Javaが常に最も指定されたメソッドを選択することを知っています。そのため、メソッドではなくメソッドa.foo(null,null);を呼び出します。しかし、なぜメソッドではなくメソッドも呼び出すのですか?Number,NumberObject,Objecta.foo(5,1.2f);Number,Numberint,Double

しかし、役立つかもしれないもう1つのこと:fafter1.2を削除すると、呼び出しは次のよう a.foo(5,1.2); になります。コンパイラエラーが発生し、Number,Numberint,Doubleメソッドのどちらかを選択できません。

あなたたちが私にそれを説明することができれば、本当に役に立ちます:)

4

3 に答える 3

18

1.2fでラップされていません。DoubleでラップされていFloatます。Floatはのサブクラスではないため(Doubleこれらはの別個のサブクラスですNumber)、使用できる最も具体的なメソッドシグネチャはですfoo(Number,Number)

を削除するとf、1.2はdoubleデフォルトで(ラッパークラスではなくプリミティブ)として扱われ、。に自動ボックス化できますDouble。ただし、5をに自動ボックス化することもできるためInteger、あいまいさが生じます。

于 2012-06-15T15:25:21.707 に答える
4

ここには2つの重要な要素があります。

まず、で1.2fはありませんDouble。それはFloatです。(int, Double)関数がまったく一致しません。(Number, Number)最適です。

第二に、あなたがそれに変更したとしても、1.2それはまだではありませんDouble。ですdouble。つまり、これはプリミティブであり、オブジェクトではありません。doubleこれで、Javaはまだ多くの不満なしに必要な関数にaを喜んで渡しDoubleますが、この場合、Javaが行うことができる2つの有効な変換を与えることによってそれを混乱させました:

  1. に変換5し、Integer 変換1.2するDouble
  2. 5プリミティブのままにしますintが、に変換1.2Doubleます。

どちらが望ましいかというルールはありません。Javaは、あいまいな関数呼び出しがあるというコンパイラエラーを生成し、(一方または両方をオブジェクトで手動でラップすることにより)どちらを選択するかを強制します。

余談ですが、取得したメソッドがある場合(int, double)、あいまいさはまったくありません。そのメソッドは、実際には既存のタイプの5andと一致する1.2ため、呼び出されます。ここでの引数のいくつかは、騒乱を引き起こすラッパーオブジェクトであるという事実です。

于 2012-06-15T15:31:20.303 に答える
1

一般的な回答:

public class OverloadingNumeric {

    public void print(int x){
        System.out.println("int");
    }

    public void print(long x){
        System.out.println("long");
    }

    public void print(float x){
        System.out.println("float");
    }

    public void print(double x){
        System.out.println("double");
    }

    public void print(Integer x){
        System.out.println("Integer");
    }

    public void print(Long x){
        System.out.println("Long");
    }

    public void print(Float x){
        System.out.println("Float");
    }

    public void print(Double x){
        System.out.println("Double");
    }

    public void print(Number x){
        System.out.println("Double");
    }

    public void print(Object x){
        System.out.println("Object");
    }

    public static void main(String[] args) {
        OverloadingNumeric obj = new OverloadingNumeric();
        /*
         * Primitives will take more precedence
         * of calling instead of wrapper class arguments,
         */
        obj.print(10);
        obj.print(10l);
        obj.print(10f);
        obj.print(10d);
        obj.print(10.1);
        //obj.print(999999999999999); Error: this letral type int is out of range
        obj.print(999999999999999l); 

        /*
         * OUTPUT
         * int
         * long
         * float
         * double
         * double
         * long
         */



        /*
         * Assume all primitive argument methods
         *  are commented. then calling the same again
         */
        obj.print(10);
        obj.print(10l);
        obj.print(10f);
        obj.print(10d);
        obj.print(10.1);

        //obj.print((Double)10); //Cannot cast int to Double 
        obj.print((double)10); //Success 
        //obj.print((Float)10); //Cannot cast int to Float 
        obj.print((float)10); //Success 
        //obj.print(null); ERROR AMBIGUOUS

        /*
         * OUTPUT
         * Integer
         * Long
         * Float
         * Double
         * Double
         * Double
         * Float
         * 
         */
    }
}




interface SuperIfc {}

class SuperClass implements SuperIfc{}

class SubClass extends SuperClass {}

public class OverloadingTest {

    public void print(SuperIfc x){
        System.out.println("SuperIfc");
    }

    public void print(SuperClass x){
        System.out.println("SuperClass");
    }

    public void print(SubClass x){
        System.out.println("SubClass");
    }

    public void print(Object x){
        System.out.println("Object");
    }

    public static void main(String[] args) {
        OverloadingTest obj = new OverloadingTest();
        SuperClass superObj = new SuperClass();
        SubClass subObj = new SubClass();
        obj.print(superObj);
        obj.print(subObj);
        obj.print(null);

        obj.print((SuperIfc)superObj);
        obj.print((SuperIfc)subObj);
        obj.print((SuperIfc)null);
        /*
         *  OUTPUT
         * SuperClass
         * SubClass
         * SubClass
         * SuperIfc
         * SuperIfc
         * SuperIfc
         */
    }
}
于 2014-05-30T06:42:15.517 に答える