128

I have a Java program that looks like this.

public class LocalScreen {

   public void onMake() {
       aFuncCall(LocalScreen.this, oneString, twoString);
   }
}

What does LocalScreen.this means in aFuncCall?

SilverNak
  • 3,283
  • 4
  • 28
  • 44
Johnny Jazz
  • 1,759
  • 3
  • 13
  • 5
  • 1
    Does this answer your question? [Using "this" with class name](https://stackoverflow.com/questions/4080868/using-this-with-class-name) – rainbow.gekota Oct 16 '22 at 20:29

5 Answers5

193

LocalScreen.this refers to this of the enclosing class.

This example should explain it:

public class LocalScreen {
    
    public void method() {
        
        new Runnable() {
            public void run() {
                // Prints "An anonymous Runnable"
                System.out.println(this.toString());
                
                // Prints "A LocalScreen object"
                System.out.println(LocalScreen.this.toString());
                
                // Won't compile! 'this' is a Runnable!
                onMake(this);
                
                // Compiles! Refers to enclosing object
                onMake(LocalScreen.this);
            }
            
            public String toString() {
                return "An anonymous Runnable!";
            }
        }.run();
    }
    
    public String toString() { return "A LocalScreen object";  }
    
    public void onMake(LocalScreen ls) { /* ... */ }
    
    public static void main(String[] args) {
        new LocalScreen().method();
    }
}

Output:

An anonymous Runnable!
A LocalScreen object

This post has been rewritten as an article here.

Rarblack
  • 4,559
  • 4
  • 22
  • 33
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • What if you have something like: `public class a { private class a { public void run() { System.out.println(a.this.toString()); } }` I'm supposing that it's the same matter; the `a.this` within `run()` must refer to the *enclosing* `a`'s `this`. Am I right? (This is how the minified code is in the OSX Kindle Previewer app's `.jar` files, I'm just trying to understand what I'm looking at.) – Matt Mc Apr 29 '15 at 05:48
  • In Java an inner class may not have the same name as any of its enclosing classes (JLS 8.1), so `a.this` in your example is not defined. I don't know if this constraint is true for bytecode. Maybe not. – aioobe Apr 29 '15 at 06:33
62

It means the this instance of the outer LocalScreen class.

Writing this without a qualifier will return the instance of the inner class that the call is inside of.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 4
    Still don't quite understand. What is the difference when I code it as "LocalScreen.this" as compared to "this" ? I tested both and the compiler only accepted "LocalScreen.this". The first parameter of aFuncCall expect aParent class which is a parent class of "Somethig". – Johnny Jazz Apr 03 '11 at 14:51
  • 1
    I'm curious about this too. Can you provide some detail on what this means? I don't see any inner classes defined in the above code; does every Java function have an associated anonymous class separate from the class it is a member of? – poundifdef Apr 03 '11 at 15:03
  • 4
    @rascher: There are inner classes in use; the OP didn't include them in the code snippet. This syntax is only supported in a non-static inner class. – SLaks Apr 03 '11 at 15:04
  • Nice that you've provided a link to official Java documentation. – Krzysztof Tomaszewski Mar 01 '18 at 12:44
16

The compiler takes the code and does something like this with it:

public class LocalScreen 
{
    public void method() 
    {
        new LocalScreen$1(this).run;
    }

    public String toString() 
    {
        return "A LocalScreen object"; 
    }

    public void onMake(LocalScreen ls) { /* ... */ }

    public static void main(String[] args) 
    {
        new LocalScreen().method();
    }
}

class LocalScreen$1
     extends Runnable
{
    final LocalScreen $this;

    LocalScreen$1(LocalScreen $this)
    {
        this.$this = $this;
    }

    public void run() 
    {
        // Prints "An anonymous Runnable"
        System.out.println(this.toString());

        // Prints "A LocalScreen object"
        System.out.println($this.toString());

        // Won't compile! 'this' is a Runnable!
        //onMake(this);

        // Compiles! Refers to enclosing object
        $this.onMake($this);
    }

    public String toString() 
    {
        return "An anonymous Runnable!";
    }
}

As you can see, when the compiler takes an inner class it converts it to an outer class (this was a design decision made a LONG time ago so that VMs did not need to be changed to understand inner classes).

When a non-static inner class is made it needs a reference to the parent so that it can call methods/access variables of the outer class.

The this inside of what was the inner class is not the proper type, you need to gain access to the outer class to get the right type for calling the onMake method.

TofuBeer
  • 60,850
  • 18
  • 118
  • 163
13

Class.this allows access to instance of the outer class. See the following example.

public class A
{
  final String name;
  final B      b;
  A(String name) {
    this.name = name;
    this.b = new B(name + "-b");
  }

  class B
  {
    final String name;
    final C      c;
    B(String name) {
      this.name = name;
      this.c = new C(name + "-c");
    }

    class C
    {
      final String name;
      final D      d;
      C(String name) {
        this.name = name;
        this.d = new D(name + "-d");
      }

      class D
      {
        final String name;
        D(String name) {
          this.name = name;
        }

        void printMe()
        {
          System.out.println("D: " + D.this.name); // `this` of class D
          System.out.println("C: " + C.this.name); // `this` of class C
          System.out.println("B: " + B.this.name); // `this` of class B
          System.out.println("A: " + A.this.name); // `this` of class A
        }
      }
    }
  }
  static public void main(String ... args)
  {
    final A a = new A("a");
    a.b.c.d.printMe();
  }
}

Then you will get.

D: a-b-c-d
C: a-b-c
B: a-b
A: a
NawaMan
  • 25,129
  • 10
  • 51
  • 77
  • The only well explained answer so far... It is indeed "Class.this allows access to instance of the outer class" and not things like "Class.this allows access to the outer class's this". A class doesn't have any "this", only instances have in order to reference themselves... – Żabojad Aug 16 '17 at 13:04
-2

I know what is your confusion.I am encounter the problem just now, it should have special scene to distinguish them.

class THIS {
  def andthen = {
    new THIS {
      println(THIS.this.## + ":inner-THIS.this.##")
      println(this.## + ":inner-this.##")
      new THIS {
        println(THIS.this.## + ":inner-inner-THIS.this.##")
        println(this.## + ":inner-this.##")
      }
    }
  }
  def getInfo = {
    println(THIS.this.## + ":THIS.this.##")
    println(this.## + ":this.##")
  }
}

You can see the diff between THIS.this and this in new THIS operation by hashcode( .## )

test in scala console :

scala> val x = new THIS
x: THIS = THIS@5ab9b447

scala> val y = x.andthen
1522119751:inner-THIS.this.##
404586280:inner-this.##
1522119751:inner-inner-THIS.this.##
2027227708:inner-this.##
y: THIS = THIS$$anon$1@181d7f28

scala> x.getInfo
1522119751:THIS.this.##
1522119751:this.##

THIS.this always point to outer THIS class which is refer by val x,but this is beyond to anonymous new operation.

LoranceChen
  • 2,453
  • 2
  • 22
  • 48