为什么调用以父class为参数的方法,而不调用以子class为参数的方法?
Why the method that gets the Father class as a parameter is called and not the method that gets the child class as a parameter?
我有一个名为 A 的 class 和一个扩展 A 的名为 B 的 class。
在使用一些方法来理解多态行为时,我 运行 陷入了一个奇怪的境地。
public class Main {
public static void main(String[] args){
B b = new B();
A a = b;
b.f1(a);
}
}
public class A {
.
.
.
public void f1(A a){
if(a instanceof B)
f1((B)a);
else
System.out.println("Nothing");
}
.
.
.
}
public class B extends A {
.
.
.
public void f1(B b){
System.out.println("B::f1(B)");
}
.
.
.
}
我希望 class A 中的 f1 首先被调用(因为 a 是 A 类型),这实际上发生了。然后我期待 f1((B)a);被调用,因为 a 是 B 的一个实例。到现在为止一切都按预期进行。但是,我认为下一个将被调用的方法是 class B 中的 f1(B) 。相反, class A 中的 f1(A) 被反复调用导致堆栈溢出异常。为什么 class B 中的 f1(B) 没有被调用? B 的一个实例是调用者,参数被强制转换为 B 类型。
f1(A a)
是classA
的实例方法。它不知道 A
的子 classes 的方法。因此,它不能调用 void f1(B b)
of class B
。因此,f1((B)a)
再次执行void f1(A a)
。
如果你想调用 f1(B b)
,你必须在 class 的实例变量上调用 f1
B
:
public void f1(A a){
if(a instanceof B) {
B b = (B)a;
b.f1(b);
} else {
System.out.println("Nothing");
}
}
你的 class A 不知道 class B 存在于某处并且具有 B.f1(B b) 函数。实际上 f1(A a) 和 f1(B b) 是两个不同的函数。您可能想要实现的目标,应该以不同的方式完成:
public class A {
//...
public void f1(A a) {
System.out.println("Nothing");
}
//...
}
public class B {
//...
public void f1(B a) {
// this is different function, because of another parameters
}
public void f1(A a) {
if(a instanceof B)
f1((B)a);
else
super.f1(a);
}
//...
}
代码必须按如下方式转换方法的调用者:
public class A {
public void f1(A a){
if(a instanceof B)
((B) this).f1(a);
else
System.out.println("Nothing");
}
}
在您的代码中,您只转换了参数。这样做会导致递归调用相同 class 的相同方法。
如果您改为转换调用者,您会通知 JVM 您想要调用子方法class,这样您就可以立即退出该方法。
重要 请注意,根据参数对调用者调用强制转换会生成 class 强制转换异常,例如在以下上下文中:
B b = new B();
A a = new A();
a.f1(b);
您不能确定接收 B 参数的方法 f1 是在 B 对象上调用的。
我有一个名为 A 的 class 和一个扩展 A 的名为 B 的 class。 在使用一些方法来理解多态行为时,我 运行 陷入了一个奇怪的境地。
public class Main {
public static void main(String[] args){
B b = new B();
A a = b;
b.f1(a);
}
}
public class A {
.
.
.
public void f1(A a){
if(a instanceof B)
f1((B)a);
else
System.out.println("Nothing");
}
.
.
.
}
public class B extends A {
.
.
.
public void f1(B b){
System.out.println("B::f1(B)");
}
.
.
.
}
我希望 class A 中的 f1 首先被调用(因为 a 是 A 类型),这实际上发生了。然后我期待 f1((B)a);被调用,因为 a 是 B 的一个实例。到现在为止一切都按预期进行。但是,我认为下一个将被调用的方法是 class B 中的 f1(B) 。相反, class A 中的 f1(A) 被反复调用导致堆栈溢出异常。为什么 class B 中的 f1(B) 没有被调用? B 的一个实例是调用者,参数被强制转换为 B 类型。
f1(A a)
是classA
的实例方法。它不知道 A
的子 classes 的方法。因此,它不能调用 void f1(B b)
of class B
。因此,f1((B)a)
再次执行void f1(A a)
。
如果你想调用 f1(B b)
,你必须在 class 的实例变量上调用 f1
B
:
public void f1(A a){
if(a instanceof B) {
B b = (B)a;
b.f1(b);
} else {
System.out.println("Nothing");
}
}
你的 class A 不知道 class B 存在于某处并且具有 B.f1(B b) 函数。实际上 f1(A a) 和 f1(B b) 是两个不同的函数。您可能想要实现的目标,应该以不同的方式完成:
public class A {
//...
public void f1(A a) {
System.out.println("Nothing");
}
//...
}
public class B {
//...
public void f1(B a) {
// this is different function, because of another parameters
}
public void f1(A a) {
if(a instanceof B)
f1((B)a);
else
super.f1(a);
}
//...
}
代码必须按如下方式转换方法的调用者:
public class A {
public void f1(A a){
if(a instanceof B)
((B) this).f1(a);
else
System.out.println("Nothing");
}
}
在您的代码中,您只转换了参数。这样做会导致递归调用相同 class 的相同方法。
如果您改为转换调用者,您会通知 JVM 您想要调用子方法class,这样您就可以立即退出该方法。
重要 请注意,根据参数对调用者调用强制转换会生成 class 强制转换异常,例如在以下上下文中:
B b = new B();
A a = new A();
a.f1(b);
您不能确定接收 B 参数的方法 f1 是在 B 对象上调用的。