Вопрос SCJP: перегрузка метода Java с помощью var-args. Каково обоснование? - PullRequest
7 голосов
/ 24 февраля 2010

Почему следующая программа выдает исключение?

public class MainClass{
  public static void main(String[] argv){
       callMethod(2);
  }
  public static void callMethod(Integer... i){
       System.out.println("Wrapper");
  }
  public static void callMethod(int... i){
       System.out.println("Primitive");
  }

}

Метод callMethod (Integer []) неоднозначен для типа MainClass

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

Первое, что пытаются сделать, - это расширить примитив. Итак, если был третий метод:

      public static void callMethod(long i){
       System.out.println("long");
      }

Код будет печатать длинный

Во-вторых, нужно упаковать примитив. Так что если бы был метод, принимающий целое число, то он был бы вызван.

Третий приоритет - это var-args.

Исходя из вышеизложенного приоритета, я бы ожидал, что вторым приоритетом будет. Я ожидал бы, что int будет заключен в Integer и (Integer ...) будет вызван. Но, конечно, этого не происходит. Вместо этого выдается исключение.

Кто-нибудь видит и может объяснить, почему расстановка приоритетов не применяется в этом примере?

Ура!

1 Ответ

9 голосов
/ 24 февраля 2010

Вы правы в том, что расширение происходит перед боксом, что, в свою очередь, предшествует var-args.

Но вы, похоже, рассматриваете первый метод как callMethod(Integer i), а не callMethod(Integer... i). Поскольку оба метода используют var-args, существует приоритет tie . То есть ни один из них не отвечает критериям для бокса, но оба соответствуют критериям для вар-аргов.

Помните, что незаконно расширять, а затем вставлять (хотя я провел некоторое исследование, прежде чем публиковать этот ответ, и обнаружил, что упаковывать, а затем расширять допустимо) Точно так же вы не получите box, а затем поведение var-args; компилятор пропускает прямо к шагу var-args и видит два метода, которые принимают var-args.

РЕДАКТИРОВАТЬ: Я должен уточнить, что вы получите поведение box-then-var-args, если нет двусмысленности. Другими словами, если бы был только один callMethod(), и потребовалось Integer... i, вы бы получили "Wrapper."

...