Методы перегрузки с помощью var-args - в сочетании с боксом и расширением - PullRequest
5 голосов
/ 14 августа 2011

При перегрузке методов, содержащих параметры, которые не совпадают, JVM всегда будет использовать метод с наименьшим аргументом, который шире, чем параметр.

Я подтвердил вышеизложенное на следующих двух примерах:

Расширение: байт расширен до int

class ScjpTest{

    static void go(int x){System.out.println("In Int");}
    static void go(long x){System.out.println("In long");}

    public static void main (String[] args){

        byte b = 5;

        go(b);

    }

}

Бокс: int упакован вЦелое число

class ScjpTest{

    static void go(Integer x){System.out.println("In Int");}
    static void go(Long x){System.out.println("In Long");}

    public static void main (String[] args){

        int b = 5;

        go(b);

    }

}

В обоих приведенных выше примерах выводится "In Int", что является правильным.Я смущен, хотя, когда ситуация включает в себя var-args, как показано в следующем примере

class ScjpTest{

    static void go(int... x){System.out.println("In Int");}
    static void go(long... x){System.out.println("In lInt");}

    public static void main (String[] args){

        byte b = 5;   //or even with:  int b = 5

        go(b);

    }

}

Вышеприведенное приводит к следующей ошибке:

ScjpTest.java:14: reference to go is ambiguous, both method go(int...) in ScjpTest and method go(long...) in ScjpTest match
                go(b);
                ^
1 error

Почему не применяется то же правилокак в предыдущих примерах?то есть расширить байт до типа int, так как он наименьший, который больше байта?

Ответы [ 3 ]

5 голосов
/ 14 августа 2011
Синтаксис

var-args - это просто псевдоним для передаваемого массива в качестве аргумента:

foo(int ... arg) равен foo(int[] arg)

Но массивы не являются иерархическими.String[] не является подклассом Object[].Точно такое же правило относится к аргументам метода.Поэтому компилятор не может различить 2 перегруженных метода, которые принимают long[] и int[] при передаче byte.

1 голос
/ 14 августа 2011

Как указал AlexR, var-args похож на массив. Массивы примитивов (таких как byte[] short[] int[] long[] float[] double[] кажутся внутренне скомпилированными в один и тот же класс. Вот почему ваши перегруженные методы неоднозначны. Однако следующий код совершенно допустим:
static void go(int... x){System.out.println("In Int");}<br> static void go(Long... x){System.out.println("In lInt");}
Он успешно компилируется (поскольку int[] и Long[] являются разными типами) и выдает результат In Int.
Если вы готовитесь к SCJP, я настоятельно рекомендую вам прочитать книгу SCJP Sun Certified Programmer для Java 6, экзамен 310-065 . Раздел Перегрузка в этой книге охватывает все приемы со смешанным боксом и вар-аргами.

1 голос
/ 14 августа 2011

На самом деле он работает в Java 7: он возвращает "In Int" и для примера varargs.Я думаю, что это было просто отсутствующей функцией в предыдущих версиях.Я не знаю, какую версию Java вы используете, но, возможно, она работает и для Java 6.

Однако я должен сказать, что был удивлен, что даже ваш первый пример работает (без varargs).Я не знал о примитивных расширяющихся конверсиях.Кстати, ваш первый и последний примеры потерпят неудачу, если вы вместо этого используете Byte, Integer и Long, поскольку между этими типами нет иерархии (за исключением того, что все они являются подклассами Number).

...