package Store;
public class Child extends Parent {
private String test = "";
public void ontest() {
this.test = "tryyyysssssssssss";
System.out.println("in constructer: " + this.test);
}
public String gettt() {
System.out.println("in child: " + this.test);
return this.test;
}
}
public abstract class Parent {
Parent() {
ontest();
}
public void ontest() {
}
public String get() {
System.out.println(gettt());
return "test";
}
public abstract String gettt();
}
public class StoreString {
public static void main(String[] args) {
Child s = new Child();
System.out.println("vaaaa:" + s.get());
}
}
输出是:
in constructer: tryyyysssssssssss
in child:
vaaaa:test
我的问题:
我想在方法Child
的{{1}}类中使用属性测试的保存值。我不确定为什么getttt()
方法中test
的值为空。
任何人都可以帮助我在这里缺少什么吗?
答案 0 :(得分:4)
在Java中,字段初始化在调用父构造函数之后发生。因此,通过调用重写方法在父构造函数中指定的任何值都将被初始化程序覆盖。
参考:Java Language specification item 12.5,具体来说,是五个步骤的列表。
答案 1 :(得分:2)
test
为空的原因是,创建实例时的执行流程:
test
醇>
因此,你可以删除默认值""
,它将保持字段不变(即,由父构造函数初始化为"tryyyysssssssssss"
)或显式调用ontest()
答案 2 :(得分:1)
只需删除测试字符串的默认初始化:
public class Child extends Parent {
private String test;
@Override
public void ontest() {
test = "tryyyysssssssssss";
System.out.println("in constructer: " + test);
}
@Override
public String gettt() {
System.out.println("in child: " + test);
return test;
}
public static void main(String[] args) {
Child s = new Child();
System.out.println("vaaaa:" + s.gettt());
}
}
abstract class Parent {
Parent() {
ontest();
}
public abstract void ontest();
public String get() {
return gettt();
}
public abstract String gettt();
}
输出:
in constructer: tryyyysssssssssss
in child: tryyyysssssssssss
vaaaa:tryyyysssssssssss
答案 3 :(得分:1)
将String test="";
更改为String test;
public class Child extends Parent {
private String test;
public void ontest() {
this.test = "tryyyysssssssssss";
System.out.println("in constructer: " + this.test);
}
public String gettt() {
System.out.println("in child: " + this.test);
return this.test;
}
}
public abstract class Parent {
Parent() {
ontest();
}
public void ontest() {
}
public String get() {
System.out.println(gettt());
return "test";
}
public abstract String gettt();
}
public class StoreString {
public static void main(String[] args) {
Child s = new Child();
System.out.println("vaaaa:" + s.get());
}
}
<强>输出强>
in constructer: tryyyysssssssssss
in child: tryyyysssssssssss
tryyyysssssssssss
vaaaa:test
答案 4 :(得分:1)
问题是JLS 12.5给出的执行顺序。这就是实际发生的事情。
明确引用这里的重要规则
[...]
3:这个构造函数不是以同一个类中另一个构造函数的显式构造函数调用开始的(使用它)。如果此构造函数用于Object以外的类,则此构造函数将以超类构造函数的显式或隐式调用开始(使用super)。
4:为此类执行实例初始值设定项和实例变量初始值设定项,将实例变量初始值设定项的值按从左到右的顺序分配给相应的实例变量,在这些顺序中,它们以文本方式出现在类的源代码中。
[...]
评估参数并处理该超类构造函数 使用这五个相同的步骤递归调用。 [...]
由于对象初始化的给定执行顺序,现在正在发生以下情况。您可以在最后一步找到问题,因为它会再次在test
中重新分配Child
。
main starts -> Child s = new Child();
Child invokes Parent Constructor as first super call
Parent constructor call method ontest().
ontest -> this.test = "tryyyysssssssssss"
Parent constructor prints "tryyyysssssssssss"
Child constructor continues and initalises the default values and sets this.test = ""
正如@swinkler已经说过的,如果您删除test
的默认初始化,则最后一步不会再将test
设置为空String
。
答案 5 :(得分:-3)
Child的构造函数应该以:public Child() {