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");
}
}
我运行了这段代码,得到如下结果:
我是B
我是B
a和aaa都有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是Atest的一个实例,我认为a2.equals(new C())
应该调用函数public boolean equals(C c)
。
任何人都可以帮助我吗?非常感谢!
答案 0 :(得分:1)
a2是Atest的一个实例,我认为a2.equals(new C())应该调用函数public boolean equals(C c)。
虽然执行时a2
的值是对Atest
实例的引用,但a2
的编译时类型只是{{ 1}}。使用编译时类型在编译时执行重载分辨率(即,选择调用哪个方法签名);它只是在执行时解析的签名的实现。
答案 1 :(得分:0)
我认为在覆盖时,要调用的方法总是由实际对象的类型决定,而不是由变量的类型决定。所以当你这样做时:
B b = new B();
A aaa = (A) b;
这种演员表并没有改变这样一个事实:" aaa"真正包含的是一个对象B.