java - 在父类和子类的构造函数中调用重写方法
问题描述
我在 Java 测试中遇到了一个问题,我错了。请向我解释为什么。
public class A {
protected String str = "A";
public static int i = 1;
public A() {
foo();
}
public void foo() {
// TODO Auto-generated method stub
System.out.println(str + " " + i);
}
}
public class B extends A {
protected String str = "B";
public static int i = 2;
public B() {
foo();
}
public void foo() {
// TODO Auto-generated method stub
System.out.println(str + " " + i);
}
}
public class Program {
public static void main(String args[]){
A a = new B();
B b = new B();
}
}
在测试中他们问我输出是什么?我回答:“A 1 B 2 A 1 B 2”,但正确答案是:“null 2 B 2 null 2 B 2”你能解释一下为什么吗?
解决方案
对于该行A a = new B();
,输出是null 2 B 2
,因为在隐式运行完成之前,您的类中的实例字段不会被初始化super()
。
在这种情况下,因为class B
is 扩展构造函数将class A
通过调用方法B()
隐式调用超类无参数构造函数A()
。super()
foo()
public A() { <---
foo(); //overriden version in class B is called |
} |
|
public B() { |
// Static fields are already initialized |
// Instance fields are not yet initialized |
// Here super() is called implicitly which calls A() ---
// Instance fields are now initialized to respective values
foo();
}
的覆盖foo()
被class B
调用,并且在 中foo()
被覆盖class B
,现在由于super()
尚未完成,实例字段class B
未初始化并且是null
。所以你看到了第一个null 2
。
然后,当控件退出super()
实例初始化程序时,运行 forB
然后foo()
ofclass B
被调用,此时实例字段的实例字段class B
被初始化为 value B
,因此您会看到B 2
打印。
您看不到静态字段的任何问题,因为它们不依赖于super()
完成的调用,它们在加载类时被初始化,因此您看到的值i
总是初始化和打印而不是null
.
line 也是如此B b = new B();
。
需要注意的重要一点是,您str
在 class 中重新定义了 instance 字段B
,因此当foo()
调用覆盖时,它实际上将引用 class 的 instance 字段B
而不是 class 的字段A
。
考虑这段代码,我str
从类中删除了该字段B
:
class A {
protected String str = "A";
public static int i = 1;
public A() {
foo();
}
public void foo() {
// TODO Auto-generated method stub
System.out.println(str + " " + i);
}
}
class B extends A {
public static int i = 2;
public B() {
foo();
}
public void foo() {
// TODO Auto-generated method stub
System.out.println(str + " " + i);
}
}
当您重新运行程序时,这将打印以下输出:
A 2
A 2
A 2
A 2
发生这种情况是因为super()
ofB
正在调用构造函数A()
,而构造函数又Object()
通过自己的super()
. 一旦在继承自的实例成员中super()
完成所有初始化。现在覆盖将打印出从继承的初始化值。A()
B
A
foo()
str
A
推荐阅读
- java - 编程存储数量并编写 else if 语句以显示正确的
- c# - 对象未填充来自 C# 扩展方法的值,但在扩展方法中具有值
- python - 我将如何使用参数在 Lua 中实现 rfind?
- spring - Spring Boot Error 控制器的不明确处理程序错误
- c++ - 循环输出中的平方数
- amazon-web-services - 如何在使用 ssh 连接时运行 localhost 地址
- json - 如何解析存储在 shell 变量中的 json 值
- javascript - React:这个番茄钟如何通过“freecodecamp 测试 12 和 13”?
- python - 如何从一个目录中读取多个文本文件,将它们全部转换为excel文件
- powershell - 使用powershell从excel中提取数据