sailaja kasanur
sailaja kasanur

Reputation: 87

Save String value of class variable

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

Answers (6)

SomeJavaGuy
SomeJavaGuy

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

Gerald Mücke
Gerald Mücke

Reputation: 11122

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

Upvotes: 2

Durgpal Singh
Durgpal Singh

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

RealSkeptic
RealSkeptic

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

swinkler
swinkler

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

Bobby Nielsen
Bobby Nielsen

Reputation: 1

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

Upvotes: -3

Related Questions