Varargs Java Неоднозначный Вызов


Я немного запутался в Java С varargs методы:

public static int sum(int ...a) {
    return 0;
}

public static double sum(double ...a) {
    return 0.0;
}

когда я пытался вызвать sum() без передачи каких-либо аргументов, то int была вызвана версия метода. Я не понимаю, почему; обычно компилятор должен вызвать ошибку.

напротив, следующий фрагмент кода генерирует ошибку компилятора, когда я пытаюсь вызвать sum без каких-либо аргументов:

public static int sum(int ...a) {
    return 0;
}

public static boolean sum(boolean ...a) {
    return true;
}
2 65

2 ответа:

общее правило, которое применяется здесь таково: если один метод сигнатура строго более конкретную чем другой, то Java выбирает его без ошибки.

интуитивно, сигнатура метода более конкретна, если вы можете полностью удалить ее, а другая, менее конкретная, будет применима к каждому существующему вызову.

при наличии выбора между подписями sum(int... args) и sum(double... args) подпись sum(int... args) более конкретно, потому что любой вызов этого метода также может быть передана sum(double... args) путем применения преобразования. То же самое не относится к sum(boolean... args) метод, который не может быть аналогичным образом преобразуются.

спецификация языка Java, версия SE 8:

15.12. Выражения Вызова Метода

15.12.2.5. Выбор наиболее конкретного метода

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

...

один применимый метод m1 более специфичен, чем другой применимый метод m2, для вызова с выражениями аргументов e1,... ЭК, если любое из следующих условий:

...

  • m2 не является общим, а m1 и m2 применимы строгим или свободным вызовом, и где m1 имеет формальные типы параметров S1, ..., Sn и m2 имеет формальные типы параметров T1, ..., Tn, тип Si является более конкретную чем Ti для аргумента ei для всех i (1 ≤ i ≤ n, n = k).

...

тип S более специфичен, чем тип T для любого выражения, если S <:>


4.10. Подтипирование

4.10.1. Подтипирование среди примитивных типов

double > 1 float

float >1 long

long >1 int

как говорится в ответ, есть правила, соблюдаемые при выборе перегруженного метода для использования.

цитата:

  1. примитивное расширение использует наименьший возможный аргумент метода
  2. тип обертки не может быть расширен до другого типа обертки
  3. вы можете вставлять из int в Integer и расширять до объекта, но не до Long
  4. расширение бьется бокс, боксерские удары ВАР-Арги.
  5. вы можете боксировать, а затем расширить (int может стать объектом через целое число)
  6. вы не можете расширить, а затем Box (int не может стать длинным)
  7. вы не можете сочетать var-args с и расширение и бокс.

(давайте переопределим Правило 1 следующим образом: "примитивное расширение использует наиболее специфичные аргумент метода, насколько это возможно.")

так что с этими правилами в разум мы можем получить представление о том, что происходит здесь:

согласно правилу номер один, примитивное расширение использует наиболее конкретный аргумент метода, насколько это возможно. С тех пор как int представляет собой десятичное число (например,1) и double представляет собой десятичное число с точностью на 32 байта больше, чем у float (например,1.0), можно сказать, что int s "меньше чем" или "меньше чем"doubleS, и по этой логике, int s можно "продвинуть" до doubles и double s можно "понизить" до int s.

проще говоря, примитив, который может быть расширен до другого примитива (например,int ->float ->double) составляет более конкретную чем другой. Например,int и более конкретную чем a double, потому что 1 может быть повышен до 1.0.

когда вы не передали никаких аргументов этим перегруженным методам vararg с тем же именем, так как возврат фактически одинаков (0 и 0.0 соответственно), компилятор решил бы использовать метод, который принимает vararg типа int поскольку более конкретную.

Итак, когда вы ввели эти же методы, принимающие в ints и boolean(типы, которые не могут быть расширены друг к другу), соответственно, компилятор не может выбрать метод для использования, начиная с int s не может быть "повышен " или" понижен", как int s,floats и doubles. поэтому он будет бросать компиляцию ошибка.

я надеюсь, это поможет вам понять, что происходит.