我已经阅读过文档和其他问题,但有些情况会让我感到很困惑。
我有这个例子,虽然经过一番思考后前3个案例非常简单,但最后4个让我感到困惑。
显然有一些关于铸造的东西,我不明白。
class A {
public static void p (Object o) { System.out.println(o); }
public void m1 (A a) { p("m1(A) in A"); }
public void m1 () { m1(new B());}
public void m2 (A a) { p("m2(A) in A");}
public void m2 () { m2(this);}
public void m3 (B b) { m2(this); }
}
class B extends A {
public void m1 (B b) { p("m1(B) in B");}
public void m2 (A a) { p("m2(A) in B");}
public void m2 (B b) { p("m2(B) in B");}
public void m3 (B b) { super.m1(b);}
}
public class Main {
public static void main(String[] args) {
A a = new B(); // Instance of class B casted to A
B b = new B(); // Instance of class B
// 1. prints "m1(A) in A"
b.m1();
// 2. prints "m2(A) in B"
b.m2();
// 3. prints "m2(A) in B"
a.m2();
// 4. prints "m1(A) in A"
a.m3((B)a);
}
}
示例1:
我希望在这里打印m1(B) in B
。
B继承A,由于没有B.m1()
,因此会调用A.m1()
来调用m1(B)
。由于我们是从B调用的,为什么它会调用A.m1(B)
而不调用B.m1(B)
?
我希望A.m1() - > B.m1(A),而不是A.m1() - > A.m1(B)
示例2:
由于4给出了"m1(A) in A"
,我在这里期待同样的事情,因为流程对我来说似乎是一样的。
仅看示例1,我期望A.m2() - > A.m2(A),而不是A.m2() - > B.m2(A)
示例3:
bb.m2();
打印m2(A) in B
。
我希望m2(A) in A
,因为它会被投放到A
。为什么要拨打B.m2(A)
?
例4。
如果它转换为B.m3()
,则会调用A
。为什么?我希望它可以调用A.m3()
,因为它已被投放
答案 0 :(得分:1)
示例1 m1(new B());
的调用位于课程A
内。 A
不知道子类的任何实现细节(例如B
的细节),因此它只知道A.m1(A)
。
示例2 :您可以添加一个简单的System.out.println(this.getClass());
来显示this
的类。它会告诉您this
的类型是$B
。您已在B
上调用该方法,并且B
知道该方法m2(B b)
,以便调用一个方法。
示例3:与5相同的原因。
示例4:它被称为B.m3()
,后者又调用super.m1(b);
。这会调用超级方法A.m1(A a)
,因为B
扩展了A
。由于B.m1(B b)
上的显式调用,它无法调用super
。如果A
中没有足够的方法,则会出现编译错误。
<强>更新强>
示例1 与示例2 之间的差异:
在示例1 b.m1();
中调用了类m1()
的方法A
。因为在调用m1()
的那一刻,编译器只知道类型是A
而不是B
。我们假设您只会看到A
类型的变量,那么您只能看到A
的方法。因此,m1(new B());
的后续调用会导致调用A
方法。编译器没有B
可用于调用它的方法
在示例2 中,类型为b
的变量B
,因此编译器可以查看A
的所有方法和B
的所有方法。因此,编译器知道方法B.m2(B b)
并可以在m2(this)
的后续调用中调用它。