8

If I write the following class:

public class Example {

      int j;
      int k;

      public Example(int j, int k) {
           j = j;
           k = k;
      }

      public static void main(String[] args) {
           Example exm = new Example(1,2);
           System.out.println(exm.j);
           System.out.println(exm.k);
      }

}

The program compiles, but when I run the program, the main method will print out two 0s. I know that in order to say that I want to initialize the instance variables in the constructor I have to write:

this.j = j;
this.k = k;

But if I don't write it, then which variable is evaluated (or considered) in the constructor (on the left and on the write hand side of the expressions)? Is is the argument or the instance variable? Does it make a difference?

Are there other cases where the use of this is obligatory?

Jean-François Corbett
  • 37,420
  • 30
  • 139
  • 188
user42155
  • 48,965
  • 27
  • 59
  • 60
  • 4
    This sort of bug is a good reason to make your parameters final. – Michael Myers Feb 05 '09 at 15:23
  • You can also have a look at: http://stackoverflow.com/questions/132777/do-you-prefix-your-instance-variable-with-this-in-java – VonC Feb 05 '09 at 15:26
  • 1
    In one of the placed I worked, they never allowed the parameters to be changed but also never allowed the parameters to be marked "final" as well. And I sort of like that style. It's, err, stylish :) – Srikanth Feb 05 '09 at 15:26
  • As a small note, whichever 'j' the compiler decides to use, your code still won't work. If it's the function parameter (it is, in this case) it won't affect this.j and if it's this.j (unlikely, at least not in any programming language I know) then it will just assign it to itself and ignore the parameter. – Tal Pressman Jul 03 '09 at 11:06

13 Answers13

32

If you don't write "this.variable" in your constructor, and if you have a local variable (including the function parameter) with the same name as your field variable in the constructor, then the local variable will be considered; the local variable shadows the field (aka class variable).

One place where "this" is the only way to go:

class OuterClass {
  int field;

  class InnerClass {
    int field;

    void modifyOuterClassField()
    {
      this.field = 10; // Modifies the field variable of "InnerClass"
      OuterClass.this.field = 20; // Modifies the field variable of "OuterClass",
                                  // and this weird syntax is the only way.
    }
  }
}
Srikanth
  • 11,780
  • 23
  • 72
  • 92
  • 1
    Nice catch: the horror of inner classes :) – Rob Grant Feb 05 '09 at 15:28
  • @Robert: Thanks! Yes, avoid as much as possible :) – Srikanth Feb 05 '09 at 15:40
  • 1
    You definitely deserved an upvote , just came around looking for "this " on google and found your simplest example . awesome :) – 0decimal0 Aug 29 '13 at 15:09
  • 1
    this is the most efficient way of explaining how the keyword "this" actually works. and yeah the weird syntax when referring to another variable from the outerclass is totally weird but very useful! – Francis Mar 17 '15 at 19:40
10

If you say just j in your constructor then the compiler will think you mean the argument in both cases. So

j = j;

simply assigns the value of the argument j to the argument j (which is a pretty pointless, but nonetheless valid statement).

So to disambiguate this you can prefix this. to make clear that you mean the member variable with the same name.

The other use of this is when you need to pass a reference to the current object to some method, such as this:

someObject.addEventListener(this);

In this example you need to refer to the current object as a whole (instead of just a member of the object).

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
6

If you don't write this, then you assign the argument to itself; the argument variables shadow the instance variables.

Rob Grant
  • 7,239
  • 4
  • 41
  • 61
5

this is useful when you want to return the object itself

return this;

This is useful because if a class has for example Method1() and Method2(), both returning this, you are allowed to write calls like

object.Method1().Method2()

Also inside a method it can be useful to pass the object itself to another function, during a call.

Emiliano
  • 22,232
  • 11
  • 45
  • 59
5

Another useful approach (though seldom used) is to declare method parameters final:

The following block will not compile, thus alerting you to the error immediately:

  public Example(final int j, final int k) {
       j = j;
       k = k;
  }
Mark Renouf
  • 30,697
  • 19
  • 94
  • 123
  • I don't like using final for local variables unless it is required (but for instance variables I use them always when possible). I find it too much clutter. Instead I use my IDE's code highlighting. See my comment here http://blog.objectmentor.com/articles/2008/10/28/data-rattle#comment-2155 – Esko Luontola Feb 05 '09 at 17:27
3

In your constructor code, you are assigning variables to themselves. 'j' is the j specified in the argument for the constructor. Even if it was the class variable j defined above, then you are still saying "j = j" ... i.e. j isn't going to evaluate differently on the left and on the right.

  public Example(int j, int k) {
       this.j = j;
       this.k = k;
  }
Philip Reynolds
  • 9,364
  • 3
  • 30
  • 37
3

What you are experiencing is called variable shadowing. Have a look at this overview for different kinds of variables in Java.

Generally speaking: The Java compiler uses the nearest variable it can find for an assignment. In a method it will first try to find a local variable and then enlarge the focus of its search to class and instance variables.

One habit I personally find good (others don't like it) is prefixing a member variable with m_ and using uppercase for CONSTANT_VARIABLES that don't change their value. Code where variable shadowing is used on purpose is very(!) difficult to debug and work with.

Thorsten79
  • 10,038
  • 6
  • 38
  • 54
  • Constants that never change should be declared final, then it's impossible to overwrite their values accidently. – Mark Renouf Feb 05 '09 at 15:31
2

You assign the parameter to itself in your example.

More generally speaking: If you don't prepend a scope to your variable, the current scope is assumed - which is the function in your case. 'this.j' tells the jre to use the variable j within the object scope - the member variable of the object.

soulmerge
  • 73,842
  • 19
  • 118
  • 155
1

Just like Robert Grant said, 'this' is how you make it clear that you are referring to a member variable instead of a local variable.

willcodejavaforfood
  • 43,223
  • 17
  • 81
  • 111
1

To answer your follow-up question about this with method, the inner class mentioned by Srikanth is still a valid example of using this: (with method this time)

public class OuterClass
{
    void f() {System.out.println("Outer f()");};
    class InnerClass {
        void f() {
            System.out.println("Inner f()");
            OuterClass.this.f();
        }
    }
}

You have the same situation with anonymous class:

You can refer to the outer class’s methods by:

  • MyOuterClass.this.yOuterInstanceMethod(),
  • MyOuterClass.myOuterInstanceMethod(),
  • or simply myOuterInstanceMethod() if there is no ambiguity.
Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
0

You might want to take a look at What is the advantage of having this/self pointer mandatory explicit?
Although using this is not mandatory in Java as you noticed I'm sure it will shed some light on the subject of using this in Java as well.

Community
  • 1
  • 1
Piotr Dobrogost
  • 41,292
  • 40
  • 236
  • 366
0

To avoid this, use an IDE (like Eclipse) and it will generate warnings in this case.

Also, make your fields final unless they absolutely can't be. There are a number of reasons (apart from this one) to do that.

Neil
  • 1,754
  • 2
  • 17
  • 30
0

This doesn't quite answer your question, but if you use Eclipse you might find "Assignment has no effect" setting useful. I am sure this will be in other IDEs too.

Miserable Variable
  • 28,432
  • 15
  • 72
  • 133