我目前正在学习我的第一个Java课程,我们最近讨论了多态和继承的主题。我正在尝试一些事情,以便更好地理解事物是如何工作的,我想知道是否有人可以帮助我理解为什么以下代码给出了输出以及当我们结合继承和覆盖方法时可能出现的问题
public class AClass {
public void m1() {
System.out.println("A.m1()");
this.m2();
}
public void m2() {
System.out.println("A.m2()");
}
public static void main(String [] args) {
AClass A = new AClass();
BClass B = new BClass();
A.m1();
A.m2();
B.m1();
public class BClass extends AClass {
@Override
public void m2() {
// TODO Auto-generated method stub
System.out.println("B.m2()");
}
}
我得到的输出是:
A.m1()
A.m2()
A.m2()
A.m1()
B.m2()
另外,如果我在我的m2()方法中为B类添加了一个super.m1()调用,我会收到堆栈溢出错误。有人能告诉我为什么会这样吗?谢谢!
答案 0 :(得分:1)
无限递归可以用以下方式解释:
无限递归是由调用B.m1()引起的。类 BClass 扩展 AClass ,因此 BClass 继承 AClass 的公共方法,即方法m1和m2。因此调用B.m1()的方法调用 BClass 的方法m1,它继承自 classA 。在m1()内部,调用this.m2()实际上等同于B.m2()。因此它从 BClass 调用重写方法m2(),因为重写方法比最初方法具有更多优先级在超级类中实现。但是当调用 BClass 中的m2时,它又通过super.m1()再次调用 AClass 的方法m1()并依次调用它通过this.m2()调用 BClass 的重写方法。这会导致无限递归。
答案 1 :(得分:1)
另外,如果我在我的m2()方法中为B类添加了一个super.m1()调用,我得到了 堆栈溢出错误。有人能告诉我为什么会这样吗?
函数调用在内存中相互堆叠。在您的代码中,
public class AClass {
public void m1() {
System.out.println("A.m1()");
this.m2();
}
public void m2() {
System.out.println("A.m2()");
}
public static void main(String [] args) {
AClass A = new AClass();
BClass B = new BClass();
B.m1();
}
public class BClass extends AClass {
@Override
public void m2() {
// TODO Auto-generated method stub
System.out.println("B.m2()");
super.m1();
}
}
您的代码会导致永无止境的序列
main
位于堆栈的底部。 B.m1()
中的语句main
调用m1()
,main
通过this.m2()
推送到堆栈中。 m1()
正文中的m2()
语句调用被覆盖的m1()
,该super.m1()
被m2()
推入堆栈。m1()
调用m2()
正文中的{{1}}语句被{{1}}推送到堆栈中。函数调用被一个接一个地推入堆栈,并且没有弹出。这会导致堆栈溢出。
答案 2 :(得分:0)
你的情况很简单。当您重写父类的方法时,您通过子类中的@Override
方法替换其实现。例如,当您致电B.m1()
时,java会在m1
中监视Bclass
方法,并使用Aclass
中具有相同签名的方法,如果找不到的话。然后它会在m2()
中查看Bclass
方法,查找并调用它。
多态性更复杂。它允许从子类调用相同的方法,而无需了解这些精确的类。我已经覆盖了related维基百科页面中的一些代码:
abstract class Animal {
abstract String talk();
}
class Cat extends Animal {
@Override
String talk() {
return "Meow!";
}
}
class Dog extends Animal {
@Override
String talk() {
return "Woof!";
}
}
void main() {
Animal[] animals = new Animal[size];
//then goes creation
for (Animal a : animals) {
a.talk();
}
}
答案 3 :(得分:0)
A.m1() - > Prints" A.m1()"因为您正在从主要方法中调用此方法。
A.m1()方法也在其中调用this.m2()。这将采用方法m2()和print - >" A.m2()"
**请注意,this.m2()与调用m2()是一回事。
A.m2() - > Prints" A.m2()"因为你是从主要的方式调用这个方法。
现在是一个稍微棘手的部分。
B.m1(),正如您所看到的,BClass没有m1()方法,但它从AClass继承它。通过继承自AClass,BClass拥有(内部)所有公共和受保护的AClass方法。这意味着BClass现在有一个m1()方法(与AClass相同)。因此,调用B.m1()将打印AClass m1() - > " A.m1()"
现在请记住,A.m1()也在其中调用this.m2()。但是由于BClass也有一个m2()方法,Java会使用那个,而这将最终打印 - > " B.m2()&#34 ;.