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

Странное поведение Java в перегрузке метода

У меня есть следующий фрагмент кода:

public static void foo(Object x) {
    System.out.println("Obj");
}
public static void foo(String x) {
    System.out.println("Str");
}

Если я называю foo(null), почему нет двусмысленности? Почему программа вызывает foo(String x) вместо foo(Object x)?

4b9b3361

Ответ 1

почему программа вызывает foo(String x) вместо foo(Object x)

Это связано с тем, что класс String распространяется от Object и, следовательно, более специфичен для Object. Таким образом, компилятор решает вызвать этот метод. Помните, что компилятор всегда выбирает наиболее специфический метод для вызова. См. Раздел 15.12.5 JLS

Если более чем один метод-член доступен и применим к необходимо вызвать один из них, чтобы обеспечить дескриптор для отправки времени выполнения. Программирование на Java язык использует правило, в котором выбран наиболее специфический метод.

Неформальная интуиция заключается в том, что один метод более конкретный, чем другой, если любой вызов, обработанный первым методом, может быть передан на другой, без ошибки типа компиляции.

Однако, если у вас есть два метода с параметром - String и Integer, вы получите ошибку ambiguity для null, поскольку компилятор не может решить, какой из них более конкретный, ковариантные типы.

Ответ 2

Он вызывает самый конкретный метод.

Так как String является подклассом Object, String является "более конкретным", чем Object.

Ответ 3

  • Тип null по определению является подтекстом любого другого ссылочного типа. Ответить JLS 4.1:

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

  • Разрешение сигнатуры метода, участвующего в вызове, следует принципу самой конкретной сигнатуры в наборе всех совместимых сигнатур. (JLS 15.12.2.5. Выбор наиболее конкретного метода).

Взятый вместе это означает, что в вашем примере выбрана перегрузка String.

Ответ 4

При выборе выбора между двумя методами, где аргумент действителен для обоих параметров, компилятор всегда будет выбирать наиболее конкретный параметр в качестве соответствия. В этом случае null является литералом, который можно обрабатывать как Object и a String. String более конкретный и подкласс Object, поэтому компилятор использует его.