2015-01-20 2 views
0
public class A { 
    public static void main(String[] args) { 
     B b = new B(); 
     A a = new B(); 
     a.f(); 
     A aaa = (A) b; 
     aaa.f(); 
    } 
    public void f() { 
     System.out.println("I'm A"); 
    } 
} 
class B extends A { 
    public void f() { 
     System.out.println("I'm B"); 
    } 
} 

я побежал этот код, и получить результат, как показано ниже:ява RTTI Приведение к базовому типу

Я B

Я B

одновременно и ааа есть экземпляр B , поэтому я думаю, что результат является разумным.

однако, я побежал другой код, например:

public class Atest { 
    public static void main(String[] args) { 
     Atest a1 = new Atest(); 
     Object a2 = new Atest(); 
     System.out.println(a1.equals(a2)); 
     System.out.println(a2.equals(a1)); 
     System.out.println(a1.equals(new C())); 
     System.out.println(a2.equals(new C())); 
    } 

    public boolean equals(Object o) { 
     System.out.println("equals(Object o) is called!"); 
     return true; 
    } 
    public boolean equals(Atest a) { 
     return true; 
    } 
    public boolean equals(C c) { 
     System.out.println("equals(C c) is called!"); 
     return true; 
    } 
} 
class C { 

} 

и, я получил результат

equals(Object o) is called! 

true 

equals(Object o) is called! 

true 

equals(C c) is called! 

true 

equals(Object o) is called! 

true 

я растерялся, что a2.equals(new C()) вызов функции public boolean equals(Object o)

a2 является экземпляр Атеста, я думаю, a2.equals(new C()) должен вызвать функцию public boolean equals(C c).

Кто-нибудь может мне помочь? Большое спасибо!

+0

возможно дубликат [Java перегрузки и наиважнейшая] (HTTP: // StackOverflow. com/questions/2469767/java-overloading-and-overriding) – immibis

ответ

1

a2 - это пример Атеста, я думаю, что a2.equals (новый C()) должен вызывать функцию public boolean equals (C c).

Хотя значение a2 во время выполнения является ссылкой на экземпляр Atest, то времени компиляции типа a2 просто Object. Разрешение перегрузки (т. Е. Выбор сигнатуры метода) выполняется во время компиляции с использованием типов времени компиляции; это только реализация этой сигнатуры, которая разрешена во время выполнения.

+0

согласно вашему ответу, A aaa = (A) b; aaa.f(); должен напечатать I'm A, но результат - B. Вы могли бы рассказать мне, в чем разница? – carey

+1

@carey: Потому что это * переопределение *, а не * перегрузка *. Подписанная подпись - это 'f()', но * реализация * подписи определяется во время выполнения (по моему утверждению) в зависимости от типа объекта. Бросок не меняет этого. –

0

Я думаю, что когда дело доходит до переопределения, метод, который нужно вызывать, всегда определяется типом фактического объекта, а не типом переменной. Так что, когда вы делаете:

B b = new B(); 
A aaa = (A) b; 

Этот бросок не меняет того факта, что «ааа» на самом деле содержит является объектом B.

Смежные вопросы