Компилятор Java должен выбирать между двумя методами сопоставления. Он всегда будет выбирать метод, который не использует переменную arity (varargs) над тем, который ее использует. Это скорее способствовало бы всем 3 аргументам int
, чтобы соответствовать первым printValue
, чем использовать varargs.
Section 15.12.2 of the JLS состояние:
Остальная часть процесса разделяется на три этапа, чтобы обеспечить совместимость с версиями языка программирования Java до версии Java SE 5.0. Фазы:
- На первом этапе (§15.12.2.2) выполняет разрешение перегрузки, не допуская бокс или распаковки, преобразование или использование метода переменной валентности вызова. Если на этом этапе не обнаружен какой-либо применимый метод, обработка продолжается до второй фазы.
Это гарантирует, что любые вызовы, которые были действительны на языке программирования Java до Java SE 5.0, не считаются неоднозначными в результате внедрения методов переменной arity, неявного бокса и/или распаковки. Однако объявление метода переменной arity (§8.4.1) может изменить метод, выбранный для выражения вызова метода данного метода, поскольку метод переменной arity рассматривается как метод фиксированной arity в первой фазе. Например, объявление m (Object ...) в классе, который уже объявляет m (Object), приводит к тому, что m (Object) больше не выбирается для некоторых выражений вызова (таких как m (null)), как m (Object [])) является более конкретным.
- Вторая фаза (§15.12.2.3) выполняет перегрузку при разрешении бокса и распаковки, но все же исключает использование вызова метода переменной arity. Если на этом этапе не обнаружен какой-либо применимый метод, обработка продолжается до третьей фазы.
Это гарантирует, что метод никогда не выбирается посредством вызова метода переменной arity, если он применим посредством вызова метода фиксированной arity.
<ол начать = «3»>
- Третий этап (§15.12.2.4) позволяет перегрузки, чтобы быть в сочетании с переменными методами арностью, бокс и распаковка.
(жирный шрифт курсив мой)
Способ согласования (первая перегрузка) находится в первой фазе, поэтому компилятор даже не рассматривает третий этап - разрешение переменных методов арности - - так печатается int
.
Один из способов выбрать вторую перегрузку (которая контринтуитивно печатает long
) - это создать массив явно, чтобы первая перегрузка не соответствовала.
printValue(new byte[]{b,b,b});