Kishore Kumar Korada
Kishore Kumar Korada

Reputation: 1264

How a class inside a method access a local variable of that method?

I'm familiar that all local variables will be stored inside stack memory and objects and static variables will be stored in heap. But then when I came across the following code which confuses me.

public class Outer {

   private int a =10;

   public void outerMethod() {      
      int x = 30;

       class Inner {
          private int b = 20;
          public void innerMethod() {
            System.out.println("The Value of a is: "+a);
            System.out.println("The Value of b is: "+b);
            System.out.println("The Value of x is: "+x);
          }
       };

       Inner inner = new Inner();
       inner.innerMethod();
    }   
}

The above code runs fine. But my question here is x is a local variable of outerMethod(). And when we create an object of Outer class, and invoke outerMethod() on it, x will be stored inside a stack frame, and I'm also defining a class definition of Inner class and creating object of it, then I'm invoking innerMethod() on it.
So that Inner Class's object must be stored inside heap. If that's the case then how could it access x??

Upvotes: 1

Views: 1253

Answers (3)

Kostas Kryptos
Kostas Kryptos

Reputation: 4111

It's true that the Inner class will be compiled to a separate class in the same package. You are correct that normally you shouldn't have access to private methods and fields of the Outer class.

But, the compiler will create some synthetic package-private methods in the bytecode-level to achieve this functionality. Now, your Inner class can access these auto-generated (hidden from you) package-private (with no access modifier) methods.

Upvotes: 1

Adam Michalik
Adam Michalik

Reputation: 9945

Inner can only access x if x is final (or, from Java 8 effectively final). Under the covers, the compiler will notice which outer variables are used by the Inner object and will pass them into the Inner constructor (these will be synthetic constructor parameters - generated by the compiler, so you will not see them). Then they will become final (again, synthetic = generated and hidden from you) fields of the Inner class. When you refer to x in the Inner class code, the compiler will substitute it with a reference to the synthetic x field in the Inner class where the value was copied.

You can see more details with this useful command:

javac -d . -XD-printflat MyFile.java

Will generate the Java code corresponding to the actual bytecode:

class Outer {

    /*synthetic*/ static int access$000(Outer x0) {
        return x0.a;
    }

    Outer() {
        super();
    }
    private int a = 10;

    public void outerMethod() {
        int x = 30;
        /*synthetic*/ {
        }
        ;
        Outer$1Inner inner = new Outer$1Inner(this, x);
        inner.innerMethod();
    }
}

class Outer$1Inner {
    /*synthetic*/ final Outer this$0;
    /*synthetic*/ final int val$x;

    Outer$1Inner(final Outer this$0, /*synthetic*/ final int val$x) {
        // Notice the synthetic references to the surrounding Outer object
        // and to the x local variable
        // Both become fields of Inner

        this.this$0 = this$0;
        this.val$x = val$x;
        super();
    }
    private int b = 20;

    public void innerMethod() {
        System.out.println("The Value of a is: " + Outer.access$000(this$0));
        System.out.println("The Value of b is: " + b);
        System.out.println("The Value of x is: " + val$x);
    }
}

You can also notice how Outer.a is accessed - since Inner is compiled to a "plain old Java class" it has to respect the visibility modifiers, so the JVM would not allow for direct access to the private field Outer.a. However, during compilation, the compiler will notice that you want to access this field from Inner, and since it's an inner class, will generate an accessor method Outer.access$000(). Since Inner has a reference to the Outer object, it can call Outer.access$000(referenceToOuter) and get the value of Outer.a.

Upvotes: 3

Ramanlfc
Ramanlfc

Reputation: 8354

Inner class object has a link to your Outer class object. what Inner is doing is essentially capturing or closing your local variable x,thereby increasing it's "lifetime" and thus your Inner class can access x.

Upvotes: 0

Related Questions