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 ответа:
общее правило, которое применяется здесь таково: если один метод сигнатура строго более конкретную чем другой, то 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
как говорится в ответ, есть правила, соблюдаемые при выборе перегруженного метода для использования.
цитата:
- примитивное расширение использует наименьший возможный аргумент метода
- тип обертки не может быть расширен до другого типа обертки
- вы можете вставлять из int в Integer и расширять до объекта, но не до Long
- расширение бьется бокс, боксерские удары ВАР-Арги.
- вы можете боксировать, а затем расширить (int может стать объектом через целое число)
- вы не можете расширить, а затем Box (int не может стать длинным)
- вы не можете сочетать var-args с и расширение и бокс.
(давайте переопределим Правило 1 следующим образом: "примитивное расширение использует наиболее специфичные аргумент метода, насколько это возможно.")
так что с этими правилами в разум мы можем получить представление о том, что происходит здесь:
согласно правилу номер один, примитивное расширение использует наиболее конкретный аргумент метода, насколько это возможно. С тех пор как
int
представляет собой десятичное число (например,1
) иdouble
представляет собой десятичное число с точностью на 32 байта больше, чем уfloat
(например,1.0
), можно сказать, чтоint
s "меньше чем" или "меньше чем"double
S, и по этой логике,int
s можно "продвинуть" доdouble
s иdouble
s можно "понизить" доint
s.проще говоря, примитив, который может быть расширен до другого примитива (например,
int
->float
->double
) составляет более конкретную чем другой. Например,int
и более конкретную чем adouble
, потому что1
может быть повышен до1.0
.когда вы не передали никаких аргументов этим перегруженным методам vararg с тем же именем, так как возврат фактически одинаков (0 и 0.0 соответственно), компилятор решил бы использовать метод, который принимает vararg типа
int
поскольку более конкретную.Итак, когда вы ввели эти же методы, принимающие в
int
s иboolean
(типы, которые не могут быть расширены друг к другу), соответственно, компилятор не может выбрать метод для использования, начиная сint
s не может быть "повышен " или" понижен", какint
s,float
s иdouble
s. поэтому он будет бросать компиляцию ошибка.я надеюсь, это поможет вам понять, что происходит.