Как разрешается неоднозначность при выборе из перегруженных методов в Java?
package org.study.algos;
public class Study {
public static void main(String[] args) {
A a = new A();
a.m1(null);
}
}
class A {
public void m1(String s) {
System.out.println("String");
System.out.println(s);
}
public void m1(Object obj) {
System.out.println("Object");
System.out.println(obj);
}
}
Здесь вывод
Строка ноль
Почему JVM разрешает метод с аргументом String?
Заранее спасибо
5 ответов
Это довольно сложный алгоритм, подробно описанный в JLS 15.12. Но здесь важна часть 15.12.2, в которой говорится, что "выбрана наиболее конкретная". Перегрузки Object и String являются "доступными и применимыми" (String применима, поскольку нулевой литерал является ссылкой всех типов), а String является более конкретным.
РЕДАКТИРОВАТЬ: Исправленный раздел, в соответствии с синтаксическим.
Эти методы "перегружены", а не "неоднозначны".
Согласно спецификации языка Java:
Когда метод вызывается (§15.12), число фактических аргументов (и любых явных аргументов типа) и типы аргументов во время компиляции используются во время компиляции, чтобы определить сигнатуру метода, который будет вызван (§15.12.2).
И §15.12.2 говорит:
Может быть более одного такого метода, и в этом случае выбирается наиболее конкретный.
String
более конкретно, чем Object
, так что пока null
совместим с обоими, метод с String
параметр выбран (есть гораздо более сложные правила, которые применяются, когда типы параметров являются частью иерархии классов или интерфейсов).
Нулевое значение может быть установлено на ссылку любого типа. Все ваши перегруженные методы находятся в одной иерархии наследования Object<- String, наименее общий из которых выбирается. Но если у вас есть два перегруженных метода, которые не находятся в одной иерархии, вы получите ошибку компиляции по поводу неоднозначных методов.
String - это Object, Object - не String, поэтому первая перегрузка более специфична, чем вторая. См. JLS 15.12.2, как упоминалось в Синтаксическом.
Я задал похожий вопрос. Джон Скит написал большой ответ.
Ссылка на мой вопрос: какая перегрузка будет выбрана для нулевой в Java?