Подтвердить что ты не робот

Перегрузка Java: число, число; ИНТ, Double

Через два дня у меня есть экзамен в 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,Number, а не метод Object,Object. Но почему a.foo(5,1.2f); также вызывает метод Number,Number, а не метод int,Double?

Но еще одна вещь, которая может быть полезна: Если я удалю f после 1.2, так что вызов будет следующим: a.foo(5,1.2); Я получаю ошибку компилятора, что он не может выбирать между методами Number,Number и int,Double...

Было бы очень полезно, если бы вы, ребята, могли мне это объяснить:)

4b9b3361

Ответ 1

1.2f не обернут Double, он завернут Float. Поскольку Float не является подклассом Double (они являются отдельными подклассами Number), наиболее специфичной сигнатурой метода может быть foo(Number,Number).

Как только вы удалите f, 1.2 по умолчанию будет обрабатываться Double (примитив, а не класс-оболочка), который может быть автобоксирован в Double. Однако 5 также может быть автобоксирован до Integer, что вызывает неоднозначность.

Ответ 2

Здесь есть два важных фактора.

Во-первых, 1.2f не является Double. Это a Float. Функция (int, Double) не совпадает вообще. (Number, Number) лучше всего подходит.

Во-вторых, даже когда вы меняете его на 1.2, он по-прежнему не является Double. Это Double. То есть, это примитив, а не объект. Теперь Java все равно с удовольствием передаст Double в функцию, которая хочет Double без большой жалобы, но в этом случае вы путаете ее, предоставив ей два действительных преобразования, которые она могла бы сделать:

  • Преобразуйте 5 в Integer и конвертировать 1.2 в Double
  • Оставьте 5 как примитив int, но преобразуйте 1.2 в Double.

Не существует правила, для которого предпочтительнее. Java создает ошибку компилятора, в которой он имеет неоднозначный вызов функции, и заставляет выбрать тот вариант, который вы предпочитаете (вручную обертывая один или оба из них в объекты).

В стороне, если у вас был метод, который принял (int, Double), не было бы никакой двусмысленности вообще: этот метод фактически соответствует существующим типам 5 и 1.2, поэтому он будет вызван. Это тот факт, что некоторые из аргументов здесь являются объектами-оболочками, вызывающими хаос.

Ответ 3

Общий ответ:

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
         */
    }
}