Utkarsh
Utkarsh

Reputation: 589

Using "this" while initialising instance variable, which object it refers and how does it work?

Before Marking this as duplicate please read the question once. I have read the question related to this from here already.

I have two java class Test2 and Test as given below. As far as I understand this refers to current object and can be used inside constructors, non-static methods and various other places as given in other question (link given above). But when I am initialising the instance variable in Test2 using this :

  1. Which object it refers to, if it refers to currently calling object, why it is not printing Hello World! ?
  2. If not, then which object is being referred here and how does it get passed to instance variable ?

Class Test2.java

public class Test2 {

  private String test2Str;
  private Test test = new Test(this);//Please notice the instance variable init

  public Test2(String str){
    this.test2Str = str;
  }

  public Test getTest() {
    return test;
  }

  public String getStr() {
    return this.test2Str;
  }

  public void setTest(Test test) {
    this.test = test;
  }

  public static void main(String[] args){
    Test2 object = new Test2("Hello World!");

    String thisStr = object.getTest().getStr();

    System.out.println(thisStr);

 }
}

Class Test.java

public class Test {

   String str;

   public Test(Test2 test){

        System.out.println(test);

        System.out.println(test.getStr());

        str = test.getStr();
   }

   public void setStr(String str){
        this.str = str;
   }

   public String getStr(){
        return this.str;
   }
}

First Output of the program :

com.avnet.spoj.lifeuniverse.Test2@56e5b723
null
null

Note : If I move instance variable initialisation inside constructor as given below. It works as expected and I can understand that. Can somebody explain above behaviour of this ?

private String test2Str;
private Test test = null;


public Test2(String str){
    this.test2Str = str;
    test = new Test(this); 
}

Second Output of the program :

com.avnet.spoj.lifeuniverse.Test2@56e5b723
Hello World!
Hello World!

Upvotes: 0

Views: 49

Answers (3)

pasaba por aqui
pasaba por aqui

Reputation: 3529

From this answers https://stackoverflow.com/a/4916805/4886927 :

Initialisers are executed before constructor bodies. (Which has implications if you have both initialisers and constructors, the constructor code executes second and overrides an initialised value).

Upvotes: 1

arcy
arcy

Reputation: 13133

this refers to the 'current instance' of the class in which it appears, but using it as your first example does during initialization is partially undefined. That code runs before the constructor runs; anything that refers to the instance of the variable before the constructor is completed has to be regarded as suspicious. This is, at the least, poor coding practice.

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 691913

The code in your first snippet:

private String test2Str;
private Test test = new Test(this);//Please notice the instance variable init

public Test2(String str){
    this.test2Str = str;
}

is equivalent to

private String test2Str = null;
private Test test = null;

public Test2(String str){
    test = new Test(this);
    this.test2Str = str;
}

So, when new Test(this) is invoked, thisis the Test2 instance being constructed, but at the time it's called, this.test2Str = str has not been executed yet, and is test2Str is thus null. That's why you see

null
null

being printed.

In your second example, new Test(this) is called after this.test2Str = str has been executed, and that's why you see

Hello World!
Hello World!

being printed.

You should really avoid leaking this to external objects, or even to overridable methods, from a constructor: these external objects will see a partially constructed object, which will thus not respect its invariants.

Upvotes: 3

Related Questions