Странное поведение 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)
?
Ответы
Ответ 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
, поэтому компилятор использует его.