0

I looked at a Why can't I use the keyword "this" when referring to fields in static methods?

and thought that accessing static members through a reference variable is ok, but using this to access such members is not okay. Look at the code below.

static int month; 

public static void setMonth(int x)
{ 
Date date = new Date();
date.month = x;  //fine, why ?
    this.month = x;  //compiler error, why ?
}

It clearly shows that this is not the same as a reference variable. If that is so, then what is it really? I need to understand the true meaning of this to understand why it cannot be accessed from a static context.

Please don't give me links to random blogs or oracle tutorials which say that this can't be used from a static context - I already know that. I want to look beyond that and understand why it can't be used.

Code in linked question -

public class Date
{

static int month; 

public static void setMonth(int x)
{ 
 this.month = x;  //compiler error
}

public static int getMonth()
{
 return month;  //compiles just fine, no error
}

}
Community
  • 1
  • 1
sky scraper
  • 2,044
  • 6
  • 24
  • 26
  • 2
    There is no `this` in anything static as youre dealing with a class, and not an instance of the class. `this` only refers to an instance. – tjb1982 Mar 24 '13 at 00:46
  • 2
    `this` refers to the *current instance* of that class. In static context, there is no current instance of the class, by definition. As a result, `this` cannot be called in static context. – FThompson Mar 24 '13 at 00:46

6 Answers6

3

When you call a non-static method, e.g. myObject.myMethod(), the compiler adds an extra secret parameter valued 'myObject' which is available inside the method as 'this'.

When you call a static method, e.g. MyClass.myStaticMethod(), there is no object to assign the secret parameter's value to, so there is no extra secret parameter, so 'this' can't have a value inside the static method.

user207421
  • 305,947
  • 44
  • 307
  • 483
2
public static void setMonth(int x)
{ 
 this.month = x;  //compiler error
}

this refers to the current object instance. No such thing in a static method, as a static method is associated to the class as a whole, not any specific instance.

So you cannot use this at all in a static method.

That the field you refer to (month) is actually a static field not an instance field does not matter. You would not have needed this here, but if you try to access it, the compiler will stop you.

public static int getMonth()
{
 return month;  //compiles just fine, no error
}

month is a static field. Just like the static method, it belongs to the class itself, and does not need an instance to be resolved.

Thilo
  • 257,207
  • 101
  • 511
  • 656
1

It is really very simple, once you understand what static means.

The this keyword (when used that way) means "the current object".

When you declare a method as static, you are saying that the method will always be called without nominating a specific object as the current object. So, when you are in a static method, there is no "current" object ... and as a logical consequence you can't use this, because it makes no sense.

There is only a "current" object if you are in an instance method or a constructor1. In the former case, the "current" object is the one that you called the method on. In the latter case it is the object you are creating.


1 ... or an instance initializer block

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
1

For the sake of completeness, this can indeed be used to reference a static field, provided it is done in non-static code so that this exists. It just can't be done where this does not exist.

public class Test {
  static int month;
  public static void main(String[] args) {
    new Test().setMonth(5);
    System.out.println(month);
  }
  public void setMonth(int x)
  { 
      this.month = x;
  }
}
Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75
1

In your code, date.month = x; is EXACTLY equivalent to Date.month = x; and that's what the compiler does at compile time. What you put on the left side actually doesn't matter. Accessing a static field or method through a reference is highly discouraged for this reason -- it looks as if the thing to the left of the dot matters, but it is not; only the compile-time type of the expression matters. Consider

(new Date()).month = x;
((Date)null).month = x;
// suppose SubDate is a subclass of Date, with its own static "month" field
((Date)new SubDate()).month = x;

All of the things above do the EXACT same thing.

So when you say

and thought that accessing static members through a reference variable is ok

Accessing static members through a reference variable should never be used. Because it is a huge illusion that has lead to numerous misconceptions and bugs; and probably should never have been allowed in Java.

newacct
  • 119,665
  • 29
  • 163
  • 224
  • Can you give me an example of the bugs caused by accessing static members through a reference variable ? – sky scraper Mar 25 '13 at 13:30
  • 2
    @skyscraper: for example, often on code samples you will see `Thread.currentThread().sleep(...);` to sleep the current thread for a period of time. Then you might be tempted to do `someOtherThread.sleep(...);` to sleep some other thread. But actually `Thread.sleep()` is a static method, and both pieces of code do the same thing -- sleep the current thread. Always writing it as `Thread.sleep(...);` will make that more clear. – newacct Mar 25 '13 at 18:20
0

The keyword this refers to the current object instance.

You cannot use it from a static context because there is no instance by definition of the concept of static in java. A static method can be accessed by all instances.

An example

public static final class MyClass {

    public static final class MyInnerClass {

        public void doStuff() {
            System.out.println(this.toString());
        }

        @Override
        public String toString() {
            return "MyInnerClass toString.";
        }
    }

    public void doStuff() {
        System.out.println(this.toString());
        new MyInnerClass().doStuff();
    }

    @Override
    public String toString() {
        return "MyClass toString.";
    }
}

public static void main(String[] args) throws InterruptedException {
    new MyClass().doStuff();
}

Output

MyClass toString.
MyInnerClass toString.

So the this in the doStuff method of MyClass refers to the instance of MyClass from within which doStuff was called.

The this in MyInnerClass does not refer to the instance of MyClass but rather to the instance of MyInnerClass from which its doStuff was called.

this always refers to the instance of the object from within which the keyword is used. If there is no instance, as is the case in a static method, the this keyword cannot be used.

Boris the Spider
  • 59,842
  • 6
  • 106
  • 166