1
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?

1
  • 2
    private String test = ""; ?? This is a empty string in the child class. Commented Aug 9, 2016 at 7:37

6 Answers 6

4

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.

Sign up to request clarification or add additional context in comments.

Comments

2

The reason why the test is empty is, the flow of execution when creating the instance:

  1. Parent constructor is invoked
  2. Child.ontest() is invoked (initializing the variable)
  3. (parent fields are initialized - nothing to do)
  4. (Child constuctor is invoked - nothing to do)
  5. Child fields are initialized - overrides the previously set field test with the empty String

So 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()

Comments

1

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

Comments

1

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

Comments

1

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.

Comments

-3

The constructor for Child should start with: public Child() {

2 Comments

The problem is not because of a missing constructor
Thank you all for quick response

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.