2014-12-06 3 views
0

Допустим, у нас есть эти два класса и один основной метод:Путаница и перегружен приведение к базовому типу методов

public class Super { 
    public void f(double d){ 
     System.out.println("Super: f(double d)"); 
    } 
    public void f(int i){ 
     System.out.println("Super: f(int i)"); 
    } 
} 

public class Sub extends Super { 
    public void f(double d){ 
     System.out.println("Sub: f(double d)"); 
    } 

    public void f(float f){ 
     System.out.println("Sub: f(float f)"); 
    } 
} 

public class M { 
    public static void main(String[] args){ 
     Sub a = new Sub(); 
     a.f(1.5f); //output: "Sub: f(float f)" 

     Super b = new Sub(); 
     b.f(1.5f); //output: "Sub: f(double d)" 
    } 
} 

Почему второй результат вызова в Sub: f(double d) и не в Sub: f(float f) как первый?

Когда я добавляю

public void f(float f) { 
    System.out.println("Super: f(float f)"); 
} 

к Super класса выходных изменений Sub: f(float f).

Учитывая такое поведение, я ожидаю, что рабочий процесс выглядит следующим образом:

  1. Как a является upcasted к Super, класс Super проверяется методом сопоставления
  2. только public void f(double d) найден, так что поплавок отлиты в двойной
  3. Теперь метод public void f(double d) в более конкретном классе Sub рассматривается и выполняется

Это правильно?

+1

Потому что нет метода 'f (float)', доступного через ссылку типа 'Super'. –

ответ

2

Чтобы понять это, отметим, что , выбирая, метод, который вызывается из серии перегруженных методов, всегда выполняется во время компиляции. Однако, метод отправка выполняется во время выполнения.

Поэтому во время компиляции видна только версия double, но она будет отправлена ​​в переопределенную версию подкласса во время выполнения.

1

Метод b.f(1.5f) рассматривается во время компиляции. Его реализация будет более конкретной (если присутствует) во время выполнения, но выбранный перегруженный метод привязан во время компиляции.

Поскольку b является по крайней мере Super единственный вывод, что компилятор может сделать вывод, что метод будет void f(double v) (поскольку Super не имеет перегрузки float), так что один выбран.

Затем во время выполнения реализация является классом Sub, благодаря динамической привязке.