2

I have written below code that is working fine but i have one doubt about synthetic method. As these are generated to access private data. but i am having public instance variable of outer class that is used in member class, so for accessing instance variable it has created synthetic method (As it is in class file!!).

code snippet is as :

public class TestInnerClass {
    public int x = 10;
        public static void main(String[] args) {
            TestInnerClass test= new TestInnerClass();
            A obj = test.new A();
            obj.display();
        }

        class A {
            void display() {
            System.out.println(x);
        }
    }
}

class file is generated as below. For inner class A as TestInnerClass$A:

import java.io.PrintStream;

class TestInnerClass$A {
    TestInnerClass$A(TestInnerClass paramTestInnerClass) {
    }

    void display() {
        System.out.println(this.this$0.x);
    }
}

class file is generated for TestInnerClass :

import java.io.PrintStream;
public class TestInnerClass {
    public int x = 10;
    public static void main(String[] args) { 
        TestInnerClass test = new TestInnerClass();
        TestInnerClass tmp13_12 = test; tmp13_12.getClass(); A obj = new A();
        obj.display();
   } 

   class A {
       A() {
       }
       void display() {
           System.out.println(TestInnerClass.this.x);
       }
   }
}

So my doubt are:

1). why the display method is having different different definition in class files??

2). why in TestInnerClass class file instance variable is accessed as TestInnerClass.this.x. but the same code is different in class file of TestInnerClass$A as this.this$0.x??

3) why JVM created synthetic method as this$0, however instance variable is public??

aioobe
  • 413,195
  • 112
  • 811
  • 826
Prashant
  • 2,556
  • 2
  • 20
  • 26
  • Code is running . I have doubt!! – Prashant Jan 22 '15 at 14:09
  • Well, I'm surprised to see that `new A()` can be called as a method of an instance as demonstrated by `A obj = test.new A();`. I thought this is not valid Java syntax. You learn something new every day. – EpicPandaForce Jan 22 '15 at 14:19

2 Answers2

3

Not entirely sure I understand your questions but I'll make an attempt to answer them:

  1. why the display method is having different definition in class files?

You can't compare java-files with class-files like that. Some features only exists in one world. Inner classes is one such feature. They don't have a direct translation into bytecode. Some code-massage is necessary, which is what you've discovered here.

  1. why in TestInnerClass class file instance variable is accessed as TestInnerClass.this.x. but the same code is different in class file of TestInnerClass$A as this.this$0.x??

Because when compiling an inner class, the implicit reference to the outer class (TestInnerClass.this) is converted to an explicit reference. Since this reference can't have the identifier this, it is called this$0.

  1. why JVM created synthetic method as this$0, however instance variable is public??

It's not a method, and as far as I can tell, it's not public. It's a field which stores a reference to the object of the enclosing class. It's needed in order to access x of that object.

aioobe
  • 413,195
  • 112
  • 811
  • 826
  • You can see the code variable x is public!! And byte code for same method is generated different! That's where I surprised. – Prashant Jan 22 '15 at 14:14
  • Your question is unclear. x is a variable. What "same method" are you talking about? – aioobe Jan 22 '15 at 14:16
  • Yes, I thought it should not be generated. – Prashant Jan 22 '15 at 14:17
  • 1
    Even though the variable is public, the inner object still has to have a reference to the outer object in order to access that public variable. – aioobe Jan 22 '15 at 14:17
  • Obviously it should have, I'm agree with you. But the both class file were having different body. So I asked!! – Prashant Jan 22 '15 at 14:20
  • Actually, the synthetic variable could have been named `this` on the byte code level without problems. But it wouldn’t be correct as it is holding the `Outer.this`. And since you can nest multiple inner classes there could be more than one outer instance, so using `this$`+number is a logical choice. – Holger Feb 20 '15 at 17:07
1

You can access variables from the outer class because they are in the closure of the inner class. Closures exists in Java but the concept doesn't exists in Java byte code. The synthetic variables and accessors you see are part of the mangling required to make closures work in java byte code.

Full disclosure: Closures in Java aren't actually closures. An actual closure captures the entire environment in which a function is created. In Java an inner class can always access the outer class members and final local variables of the method in which it was created. It can't however access non final local variables as would be possible in a language like say JavaScript.

M.P. Korstanje
  • 10,426
  • 3
  • 36
  • 58
  • 2
    Just a small clarification on top of your answer. We don't actually have Closures in Java not even with lambdas in java8 as they deal with only effectively final variables. If u look at closures at other languages like JavaScript, the object outlives the method in which it is created but still has access to all local variables within that method :) Coming to OP question, Inner Classes defined within in a class always have access to the member (private or public) variables of the class in which they're defined. – Arkantos Jan 22 '15 at 17:56
  • Added a note. I think it is easier to start out with the concept and explain the limitations afterwards rather then explain apparently arbitrary but useful access abilities. – M.P. Korstanje Jan 22 '15 at 19:51