Как компилятор Java способен различать эти два конструктора/методы?
public class MyClass {
private String string;
private Object[] objects;
// constructor 1
public MyClass(String string, Object... objects) {
this.string = string;
this.objects = objects;
}
// constructor 2
public MyClass(String string) {
this.string = string;
}
public static void main(String[] args) {
MyClass myClass = new MyClass("foobar");
}
}
В этом случае, как компилятор Java решил использовать constructor 2
вместо constructor 1
? Почему нет The constructor ... is ambiguous
или аналогичной ошибки?
PS: вопрос также работает с классическими методами.
Ответы
Ответ 1
Это всегда самый специфический метод, который вызывается.
new MyClass("foobar");
выполняет поиск для вызова этого конструктора, который принимает объект типа String
, поскольку он только аргумент.
и метод var-args
будет использоваться, если метод соответствия non-var-args
не существует.
Ответ 2
Метод/конструктор var-args будет выбран , только если нет метода/конструктора var-arg. Поэтому понятно, почему компилятор выбирает MyClass(String string)
.
Ответ 3
Как я понимаю, конструкторы и методы varargs - это только синтаксический сахар, который преобразуется в объявления массива. Таким образом, ваш конструктор 1 во время компиляции будет почти равен:
public MyClass(String string, Object[] objects) {
this.string = string;
this.objects = objects;
}
Это означает, что если вы хотите построить экземпляр MyClass
следующим кодом:
MyClass obj = new MyClass("Hello", "1", "2");
Он будет равен:
MyClass obj = new MyClass("Hello", new Object[]{"1", "2"} );
Ответ 4
1-й ответ
Если у вас несколько конструкторов, конструкторы отличаются друг от друга объявлением параметров. Когда класс инициализируется, Java вызовет правый конструктор, который соответствует данным аргументам и типу.
Пример: если вы создадите 2 конструктора с одним и тем же параметром, он покажет вам Duplicate method or ambiguous error
2-й ответ
Метод с тем же самым и другим прототипом называется методом overloading в java.
Вот почему no The constructor ... is ambiguous error occurs
в случае подрядчика, а также в случае метода.
Ответ 5
JVM будет искать соответствие Exact для передачи значений в переменные в методах/конструкторе, , если он не сможет найти точное соответствие, он будет обрабатывать значения как Object.
Ответ 6
jls-15.12.2 утверждает, что компилятор сначала будет выглядеть наилучшим образом без autoboxing или var agrs. Constructor #2
подходит для вашего случая.
Если бы его там не было, будет применено первое автобоксирование, то есть любой метод с суперкомпьютом параметров String i.e. Будет вызван объект.
// constructor 2
public MyClass(Object string) {
this.string = string.toString();
}
Теперь, даже после применения autoboxing, компилятор не сможет найти наилучшее совпадение, он пойдет для var args. Итак, если вы удалите конструктор 2 из своего кода, вызывается первый конструктор.