Отправка метода 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. Я мог бы скомпилировать код Хемаля без проблем, но мой по-прежнему не компилируется. Единственное отличие, которое я вижу, состоит в том, что методы Хемаля являются статическими, а мои - нет. Но я действительно не понимаю, почему это должно иметь значение...?
Обновление 2: решено. У меня в классе был другой метод foo(Runnable), поэтому диспетчер не смог однозначно выбрать наиболее специфический метод. (См. Мой комментарий во втором ответе Хемаля.) Спасибо всем за вашу помощь.
4 ответа
Какую версию 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)");
}
}
Потому что второй закомментированный вызов с нулем неоднозначен для компилятора. Литерал null может быть строкой или объектом. Принимая во внимание, что присвоенное значение имеет определенный тип. Вам нужно привести значение null, например test.foo((String)null), чтобы убрать неоднозначность.
Кто-нибудь пробовал пример???
С 1.6.0 foo(null) отправляется наиболее специфичному методу, который является foo(String)...
Если вы добавите новый метод, скажем, foo(Integer), компилятор не сможет выбрать наиболее конкретный применимый метод и выдаст ошибку.
-Патрик
Извините, что использую ответ для комментария, но мне нужно опубликовать код, который не помещается в комментарии.
@ Ян, я также могу скомпилировать и запустить следующее. Можете ли вы опубликовать полный код, который компилируется с одной закомментированной строкой, так что, если я раскомментирую эту строку, она не будет скомпилирована?
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)");
}
}