Метод отправки Java с нулевым аргументом
Почему (по-видимому) имеет значение, передаю ли я null
в качестве аргумента напрямую или передаю Object
, которому я присвоил значение null
?
Object testVal = null;
test.foo(testVal); // dispatched to foo(Object)
// test.foo(null); // compilation problem -> "The method foo(String) is ambiguous"
public void foo(String arg) { // More-specific
System.out.println("foo(String)");
}
public void foo(Object arg) { // Generic
System.out.println("foo(Object)");
}
Другими словами, почему второй комментарий к foo(...)
не был отправлен на foo(Object)
?
Обновление: Я использую Java 1.6. Я мог бы скомпилировать код Hemal без проблем, но мой до сих пор не компилируется. Единственное различие, которое я вижу, это то, что методы Hemal являются статическими, а мои - нет. Но я действительно не понимаю, почему это должно иметь значение...?
Обновление 2:. У меня был еще один метод foo (Runnable) в моем классе, поэтому диспетчер не мог однозначно выбрать один наиболее специфический метод. (См. Мой комментарий в Гемале, второй ответ.) Спасибо всем за вашу помощь.
Ответы
Ответ 1
Какую версию Java вы используете? С 1.6.0_11 компилируется и запускается код (вставленный ниже).
Я уверен, что очевидно, что foo(testVal)
переходит в foo(Object)
.
Причина, по которой foo(null)
переходит в foo(String)
, немного сложна. Константа null
имеет тип nulltype
, который является подтипом всех типов. Таким образом, этот nulltype
расширяет String
, который продолжается Object
.
Когда вы вызываете foo(null)
, компилятор ищет перегруженный метод с наиболее специфическим типом. Поскольку String
более конкретный, то Object
, который является вызываемым методом.
Если у вас была другая перегрузка, которая была такой же конкретной, как String, скажем foo(Integer)
, тогда вы получите двусмысленную ошибку перегрузки.
class NullType {
public static final void main(final String[] args) {
foo();
}
static void foo()
{
Object testVal = null;
foo(testVal); // dispatched to foo(Object)
foo(null); // compilation problem -> "The method foo(String) is ambiguous"
}
public static void foo(String arg) { // More-specific
System.out.println("foo(String)");
}
public static void foo(Object arg) { // Generic
System.out.println("foo(Object)");
}
}
Ответ 2
Потому что второй вызов с комментариями с нулем неоднозначен для компилятора. Литеральный нуль может быть строкой или объектом. Если присвоенное значение имеет определенный тип. Вам нужно указать нуль, например. test.foo((String) null), чтобы удалить двусмысленность.
Ответ 3
Кто-нибудь пробовал пример???
С 1.6.0 foo (null) отправляется наиболее применимый метод, который является foo (String)...
Если вы добавляете новый метод say foo (Integer), компилятор не может выбрать наиболее подходящий применимый метод и показывает ошибку.
-Patrick
Ответ 4
Извините за использование ответа, за комментарий, но мне нужно отправить код, который не подходит для комментариев.
@Yang, я также могу скомпилировать и запустить следующее. Можете ли вы опубликовать полный код, который компилируется с одной строкой, прокомментированной так, что если я раскомментирую эту строку, она не будет компилироваться?
class NullType {
public static final void main(final String[] args) {
foo();
new Test().bar(new Test());
}
static void foo()
{
Object testVal = null;
foo(testVal); // dispatched to foo(Object)
// foo(null); // compilation problem -> "The method foo(String) is ambiguous"
}
public static void foo(String arg) { // More-specific
System.out.println("foo(String)");
}
public static void foo(Integer arg) { // More-specific
System.out.println("foo(Integer)");
}
public static void foo(Object arg) { // Generic
System.out.println("foo(Object)");
}
}
class Test
{
void bar(Test test)
{
Object testVal = null;
test.foo(testVal); // dispatched to foo(Object)
test.foo(null); // compilation problem -> "The method foo(String) is ambiguous"
}
public void foo(String arg) { // More-specific
System.out.println("foo(String)");
}
public void foo(Object arg) { // Generic
System.out.println("foo(Object)");
}
}