Отправка метода Java с нулевым аргументом - PullRequest
12 голосов
/ 18 декабря 2008

Почему (по-видимому) имеет значение, передам ли я 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 ]

24 голосов
/ 18 декабря 2008

Какую версию 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 голосов
/ 18 декабря 2008

Потому что второй закомментированный вызов с нулем неоднозначен для компилятора. Литерал null может быть строкой или объектом. Принимая во внимание, что присвоенное значение имеет определенный тип. Вам нужно разыграть ноль, например test.foo ((String) null) для удаления неоднозначности.

1 голос
/ 18 декабря 2008

Извините, что использую ответ для комментария, но мне нужно опубликовать код, который не помещается в комментарии.

@ Ян, я также могу скомпилировать и запустить следующее. Можете ли вы опубликовать полный код, который компилируется с одной закомментированной строкой, так что, если я раскомментирую эту строку, она не будет скомпилирована?

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)");
  }
}
1 голос
/ 18 декабря 2008

Кто-нибудь пробовал пример ???

С 1.6.0 foo (null) отправляется наиболее специфическому методу, который является foo (String) ...

Если вы добавите новый метод, скажем, foo (Integer), компилятор не сможет выбрать наиболее конкретный применимый метод и выдаст ошибку.

-Patrick

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...