Java继承基类使用派生类方法
最近我偶然发现了Java测试,发现了一个奇怪的行为Java继承基类使用派生类方法,java,inheritance,Java,Inheritance,最近我偶然发现了Java测试,发现了一个奇怪的行为 class MainOne { private int i = 5; public MainOne() { System.out.println("MainOne says that I is " + getI()); } public int getI() { System.out.println("MainOne ge
class MainOne {
private int i = 5;
public MainOne() {
System.out.println("MainOne says that I is " + getI());
}
public int getI() {
System.out.println("MainOne getI was used");
return i;
}
}
public class TheTest extends MainOne {
private static int i = 10;
public TheTest() {
System.out.println("TheTest says that I is " + super.getI());
}
public int getI() {
System.out.println("TheTest getI was used");
return i;
}
public static void main(String[] args) {
TheTest test = new TheTest();
}
}
结果是:
使用了测试的getI
梅因说我10岁了
使用了MainOne-getI
考试说我5岁
问题是,发生了什么?基类如何使用它的后代方法?这是关于执行顺序和构造函数继承的
test
构造函数隐式调用super
MainOne
构造函数
所以
召唤
public MainOne() {
System.out.println("MainOne says that I is " + getI());
}
由于多态性,它调用重写的getI()
public int getI() {
System.out.println("TheTest getI was used");
return i;
}
i
这里是测试中声明的静态i
。最后
super.getI());
使用MainOne
的i
调用
你因此得到
TheTest getI was used
MainOne says that I is 10.
MainOne getI was used
TheTest says that I is 5
请注意多态性不适用于字段,并且字段(无论是静态字段还是实例字段)可能会在父类中隐藏同名字段。在这个问题中有两点需要注意
super.getI()在MainOne内部调用
public TheTest() {
System.out.println("TheTest says that I is " + super.getI());
}
即使方法被重写,此调用也会强制转到超类
子类中的字段i
定义为static
字段
根据此字段是否为静态字段,结果会有所不同。当从test
构造函数调用重写的getI()
时,调用转到MainOne
classes方法。但是,当发生此调用时,test
类的实例字段尚未初始化为指定的值(但仅为默认值)
如果测试中的字段i
是一个实例字段,getI()
将打印0而不是10
这里很难描述调用顺序的细节。但是,如果您想了解更多详细信息,请参阅下文
new TheTest()
-> super() - implicitly invoke default constructor
-> inside MainOne() constructor
-> System.out.println("MainOne says that I is " + getI());
-> this results in a getI() invocation
-> since getI() is overridden by subclass
-> invoke on TheTest instance, not MainOne class.
-> TheTest's instance fields not given the assigned values
-> TheTest's static fields have got the assigned values
<- string concatenation completes for System.out.println()
<- MainOne constructor (or the super) is completed
<- super() completes
-> System.out.println("TheTest says that I is " + super.getI());
-> this results in a getI() invocation
-> however explicit super.getI() forcefully goes to super class
-> invoke on MainOne (super) instance, not TheTest class.
<- string concatenation completes for System.out.println()
<- new TheTest() constructor completes
newthetest()
->super()-隐式调用默认构造函数
->在MainOne()构造函数中
->println(“MainOne说我是”+getI());
->这将导致一个getI()调用
->因为getI()被子类重写
->在测试实例上调用,而不是在一个类上调用。
->测试的实例字段未指定指定值
->测试的静态字段具有指定的值
然而,显式的super.getI()强制转到super类
->在MainOne(超级)实例上调用,而不是在Test类上调用。
什么意思?它们在构造函数中被调用。但是多态性是如何开始的呢?基类在调用getI()方法时不应该知道它的派生类。@基类不知道,但JVM知道。这是后期绑定的结果。哦,这是有道理的。非常感谢。不过,这是一个棘手的情况。Rogar考虑阅读多态性以及它是如何实现的。您可以开始了解有关后期绑定的一些详细信息。
new TheTest()
-> super() - implicitly invoke default constructor
-> inside MainOne() constructor
-> System.out.println("MainOne says that I is " + getI());
-> this results in a getI() invocation
-> since getI() is overridden by subclass
-> invoke on TheTest instance, not MainOne class.
-> TheTest's instance fields not given the assigned values
-> TheTest's static fields have got the assigned values
<- string concatenation completes for System.out.println()
<- MainOne constructor (or the super) is completed
<- super() completes
-> System.out.println("TheTest says that I is " + super.getI());
-> this results in a getI() invocation
-> however explicit super.getI() forcefully goes to super class
-> invoke on MainOne (super) instance, not TheTest class.
<- string concatenation completes for System.out.println()
<- new TheTest() constructor completes