Подтвердить что ты не робот

Почему Java предпочитает вызывать двойной конструктор?

public class test {
    test(double[] a)
    {
        System.out.println("in double");
    }
    test(Object a)
    {
        System.out.println("in object");
    }
    public static void main(String args[])
    {
        new test(null);
    }
}

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

ПРИМЕЧАНИЕ связанный вопрос может не дублироваться, потому что этот вопрос связан с примитивным типом данных vs Object

4b9b3361

Ответ 1

Причина в том, что Java интерпретирует null как любой тип, и при выборе метода для вызова он выберет наиболее специфический метод, который сначала будет использовать типы аргументов. Поскольку null может быть типа double[], а double[] - Object, компилятор выберет метод, который принимает double[]. Если выбор включает одинаково возможные, но несвязанные типы, например. double[] и String, тогда компилятор не сможет выбрать метод, и это приведет к ошибке неоднозначного вызова метода.

JLS, раздел 4.1, говорится:

Нулевая ссылка всегда может быть назначена или применена к любому ссылочному типу (§5.2, §5.3, §5.5).

На практике программист может игнорировать нулевой тип и просто притворяться, что null - это просто специальный литерал, который может быть любого ссылочного типа.

Ответ 2

Оба конструктора применимы, потому что null можно конвертировать в оба Object и double[] - поэтому компилятору необходимо использовать разрешение перегрузки, чтобы определить, какой конструктор вызвать.

JLS 15.9.3 использует JLS 15.12.2, чтобы определить "наиболее конкретную" подпись конструктора для используя, на основе которого конструктор имеет наиболее конкретные типы параметров, согласно JLS 15.12.2.5. Точные детали немного неясны (IMO), но в этом случае основное эмпирическое правило "если вы можете конвертировать из T1 в T2, но не от T2 до T1, а более точный T1", это достаточно хорошо.

double[] - более конкретный тип, чем Object, потому что существует неявное преобразование от double[] до Object, но не наоборот.