Как компилятор Java способен различать эти два конструктора/методы? - программирование

Как компилятор 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: вопрос также работает с классическими методами.

4b9b3361

Ответ 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 из своего кода, вызывается первый конструктор.