Java 遗传、多态性问题
我目前正在学习我的第一个Java课程,我们最近讨论了多态性和继承的主题。为了更好地理解事物是如何工作的,我尝试了一些事情,我想知道是否有人能帮助我理解为什么下面的代码会给我输出,以及当我们结合继承和重写方法时可能出现的问题Java 遗传、多态性问题,java,inheritance,polymorphism,overriding,Java,Inheritance,Polymorphism,Overriding,我目前正在学习我的第一个Java课程,我们最近讨论了多态性和继承的主题。为了更好地理解事物是如何工作的,我尝试了一些事情,我想知道是否有人能帮助我理解为什么下面的代码会给我输出,以及当我们结合继承和重写方法时可能出现的问题 public class AClass { public void m1() { System.out.println("A.m1()"); this.m2(); } public void m2() { System.out.println("A.m
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()
此外,如果在类B的m2()方法中添加super.m1()调用,则会出现堆栈溢出错误。谁能告诉我为什么会这样?谢谢 你的情况很简单。当您重写父类的方法时,将其实现替换为子类中的
@override
方法。例如,当您调用B.m1()
时,java监视Bclass
中的m1
方法,如果没有找到,则使用与Aclass
中签名相同的方法。然后它观察Bclass
中的m2()
方法,找到一些并调用它
多态性更为复杂。它允许从子类调用相同的方法,而不需要知道这些确切的类。我覆盖了维基百科页面上的一些代码:
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();
}
}
A.m1()-->打印“A.m1()”,因为您正在从主方法调用此方法
方法也在其内部调用此.m2()。这将进入方法m2()并打印-->“A.m2()”
**注意,这个.m2()与调用m2()是一样的
A.m2()-->打印“A.m2()”,因为您是从主目录调用此方法
现在是稍微棘手的部分
如您所见,BClass没有m1()方法,但它从AClass继承了它。通过从AClass继承,BClass(在内部)拥有AClass的所有公共和受保护的方法。这意味着BClass现在有一个m1()方法(与AClass相同)。因此,调用B.m1()将打印AClass m1()-->“A.m1()”
现在请记住,A.m1()也在其内部调用此.m2()。但由于BClass也有一个m2()方法,Java将使用该方法,这将最终打印-->“B.m2()” 无限递归可以用以下方式解释: 无限递归是由调用B.m1()引起的。类BClass扩展了AClass,因此BClass继承了AClass的公共方法,即方法m1和m2。因此,方法调用B.m1()调用从classA继承的BClass的方法m1。在m1()内部,调用this.m2()实际上相当于B.m2()。因此它从BClass调用被重写的方法m2(),因为被重写的方法比最初在超类中实现的方法具有更高的优先级。但是当调用BClass中的m2时,它反过来调用方法m1()再次通过super.m1()调用AClass的重写方法,然后再次通过this.m2()调用BClass的重写方法。这会导致无限递归 另外,如果我在类B的m2()方法中添加一个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
位于堆栈的底部李>
main
中的语句B.m1()
调用m1()
,它被推到main
上的堆栈中李>
m1()
的主体中的语句this.m2()
调用被重写的m2()
,它被推到堆栈中的m1()
m2()
主体中的语句super.m1()
调用m1()
,该语句被推到堆栈中的m2()
m2
inBClass
调用AClass
中的m1
,它调用m2
,等等(无限递归)。谢谢你的回复,如果你不介意的话,可以一步一步地看一下,就像我不明白为什么我们会有无限递归一样,为什么它会继续运行?调试它并逐步完成代码。谢谢!这是有道理的,但是我仍然不能完全确定为什么程序会崩溃,我不明白为什么我们会进入一个无限循环(当我添加super.m1()方法时)当你在B.m2()
方法的开头添加super.m1()
时,代码是这样的:B.m1()
->A.m1()
->B.m1()
->A.m1()
一次又一次。更详细地说:当调用B.m1()时,将执行A.m1()中的代码,因为尽管类B扩展了类A,但它不会覆盖m1。问题是A.m1()调用m2()(在打印“A.m1()”)之后),它在B中有自己的实现,因此它是被调用的。但是如果你在里面放一个super.m1(),会再次调用a.m1(),“a.m1()”会再次打印,B.m2()会再次调用,依此类推。知道了?