2015-08-12 2 views
6

Я просто написал код со следующей структурой:Почему это не вызывает двусмысленности?

public void method(int x) { 
    //... 
} 

public void method(int x, String... things) { 
    //... 
} 

Я был очень удивлен, что это компилируется, и что если я вызван

method(3); 

то выбрал бы первый. Очевидно, что в некотором смысле это естественный выбор, но если первый метод не существует, это было бы разумным способом вызова второго (с пустым массивом varargs). Так что, конечно, это должно считаться неоднозначным и производить ошибку времени компиляции?

Или это рассматривается как частный случай?

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

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

+0

Вы вызвали метод с 1 параметром, почему он должен назвать тот, у кого 2 необходимо? – loli

+2

@loli, потому что нет ни одного с двумя необходимыми. Вторая имеет параметр varargs, что означает, что часть 'String ...' может принимать любое количество аргументов, включая ноль. –

+0

@ chiastic-security А я не знал, что это эквивалент Java, я думал, что вы написали ... потому что вам было слишком лениво найти [] на клавиатуре – loli

ответ

10

Согласно Chapter 15 спецификации языка Java, поиск применимого метода осуществляется в три этапа.

Первый этап (§15.12.2.2) выполняет перегрузочное разрешение без разрешения преобразования бокса или распаковки или использования вызова метода переменной arity. Если на этом этапе не обнаружен какой-либо применимый метод, обработка продолжается до второй фазы.

Итак, первый метод уже применяется в первой фазе. Остальные фазы пропускаются; метод String ... будет рассмотрен только в третьей фазе:

Третий этап (§15.12.2.4) позволяет перегрузке сочетаться с методами переменной arity, боксом и распаковкой.

0

Аргумент типа первого метода является

int x 

типы аргументов второго метода

int x, String[] things 

Поэтому эти два метода делают не имеют одинаковые S и нет никакой двусмысленности. @Glorfindel объясняет, как Java решает, какой метод вызывать, но если вы хотите вызвать второй метод без things, вы можете пройти в пустой массив.

method(6, new String[0]);