Reputation: 87
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());
}
}
output is:
in constructer: tryyyysssssssssss
in child:
vaaaa:test
My question:
I would like to use saved value of attribute test in Child
class in method getttt()
. I am not sure why value of test
is blank in gettt
method.
Could any one help me what is missing here?
Upvotes: 1
Views: 78
Reputation: 7347
The Problem is the execution Order given by the JLS 12.5. That´s what actually happening.
Explicity quoting the important rules here
[...]
3: This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super).
4: Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class.
[...]
Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. [...]
The following is now happening due to the given execution order of object initialization. You´ll find the problem in the last step as it reassigns test
in Child
again.
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 = ""
as @swinkler already said, if you remove the default intialization of test
the last step wont set test
to an empty String
again.
Upvotes: 1
Reputation: 11122
The reason why the test
is empty is, the flow of execution when creating the instance:
test
with the empty StringSo you may either remove the default value ""
which will leave the field as is (namely, initialized with "tryyyysssssssssss"
by the Parent constructor) or explicitly invoke ontest()
Upvotes: 2
Reputation: 11953
Change String test="";
to 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());
}
}
Output
in constructer: tryyyysssssssssss
in child: tryyyysssssssssss
tryyyysssssssssss
vaaaa:test
Upvotes: 1
Reputation: 34618
In Java, field initialization happens after the call to the parent constructor. So whatever value you assigned in the parent constructor by calling the overridden method is going to be overwritten by your initializer.
Reference: Java Language specification item 12.5, specifically, the list of five steps.
Upvotes: 4
Reputation: 1701
Just remove the default initialization of the test String:
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();
}
Output:
in constructer: tryyyysssssssssss
in child: tryyyysssssssssss
vaaaa:tryyyysssssssssss
Upvotes: 1