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

Метод отправки 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) в моем классе, поэтому диспетчер не мог однозначно выбрать один наиболее специфический метод. (См. Мой комментарий в Гемале, второй ответ.) Спасибо всем за вашу помощь.

4b9b3361

Ответ 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)");
  }
}