Полиморфизм и перегрузка метода - PullRequest
26 голосов
/ 10 февраля 2011

У меня быстрый и прямой вопрос:

У меня есть простой класс:

public class A
{
    public void m(Object o)
    {
      System.out.println("m with Object called");
    }

    public void m(Number n)
    {
       System.out.println("m with Number called");
    }
    public static void main(String[] args)
    {
       A a = new A();
       // why will m(Number) be called?
       a.m(null);
    }
}

ОБНОВЛЕНИЕ: на самом деле это метод с Number, который фактически вызывается.Извините за путаницу.

Если я вызываю am (null), он вызывает метод с параметром Number.

Мой вопрос: почему это так?где в спецификации языка Java это указано?

Ответы [ 5 ]

26 голосов
/ 10 февраля 2011

Прежде всего, на самом деле он вызывает m(Number).

Это происходит потому, что оба метода применимы , но m(Number) является наиболее конкретным методом, поскольку любой аргумент m(Number) может быть передан m(Object), но не наоборот.

Если вы замените m(Object) на m(String) (или добавите другой метод, такой как m(Date)), компилятор сообщит о неоднозначности, поскольку наиболее конкретный метод не может быть идентифицирован.

См. Раздел Выбор наиболее конкретного метода в спецификации Java.

12 голосов
/ 10 февраля 2011
  1. Это не полиморфизм или переопределение. Это метод перегрузка .
  2. Я проверил это, и вызывается конкретный метод (не m (Object)), и в соответствии со спецификацией всегда вызывается конкретный метод. Какая перегрузка будет выбрана для нулевого значения в Java?
7 голосов
/ 10 февраля 2011

еще один связанный с вами вопрос для размышления:

public static void main(String[] args)
{
   A a = new A();
   Object n = new Integer(1);
   a.m(n); // which method will be called?
}
1 голос
/ 10 февраля 2011

Мои 2 цента.Метод с аргументом Number - это тот, который вызывается, поскольку Number расширяет объект.У меня была похожая ситуация в прошлом, я переопределил метод и поместил компонент вместо JComponent (по ошибке).Мне потребовалась одна неделя, чтобы выяснить причину, по которой мой метод никогда не вызывался.Я выяснил, что если между перегруженными методами существуют некоторые отношения наследования, JVM сначала сопоставляет более глубокое в иерархии классов.

0 голосов
/ 10 февраля 2011

Object является типом по умолчанию в Java. Если вы реорганизуете свой метод m(Object o) в m(String o), у вас будет ошибка времени компиляции, говорящая, что вызов m(null) неоднозначен, потому что Java не может определить, какой класс между String и Number по умолчанию равен null

Кроме этого, между m(Object o) и m(Number o) вызов m(null) вызовет m(Number o), потому что это самый специализированный метод. В противном случае вам нужно будет привести null в Object (или что-либо, кроме Number).

a.m((String) null);
...