Sam
Sam

Reputation: 566

Way to call inner class by outer class

I know that to instantiate a member inner class, you have two different constructors:

First:

Outer out = new Outer();
Outer.Inner in = out.new Inner();

Second:

Outer.Inner in = new Outer().new Inner();

Now, I don't know why this code compiles:

public class Outer {

    private String greeting="Hi";

    protected class Inner {
        public int repeat=3;

        public void go() {
            for (int i =0; i<repeat; i++) {
                System.out.println(greeting);
            }
        }
    }

    public void callInner() {
        Inner in = new Inner(); //in my opinion the correct constructor is Outer.Inner in = new Inner()
        in.go();
    }

    public static void main(String[] args) {
        Outer out = new Outer();
        out.callInner();

    }
}

Why does it compile?

Thanks a lot!

Upvotes: 3

Views: 1766

Answers (4)

LuCio
LuCio

Reputation: 5173

As your explanation shows, you need an instance of Outer to create an instance of Inner. Since the method callInner is an instance method of Outer (it is not declared static) there is already an instance of Outer present: this

The code could also be written like that:

public void callInner() {
    Outer out = this;
    Inner in = out.new Inner();
    in.go();
}

Now the code looks similar to your first example.

But let's keep the code as shown:

public void callInner() {
    Inner in = new Inner();
    in.go();
}

Now if we look under the hood it's basically the same:

 public void callInner();
   Code:
      0: new           #21                 // class playground/Outer$Inner
      3: dup
      4: aload_0
      5: invokespecial #23                 // Method playground/Outer$Inner."<init>":(Lplayground/Outer;)V
      8: astore_1
      9: aload_1
     10: invokevirtual #26                 // Method playground/Outer$Inner.go:()V
     13: return

On line 4 we get aload_0 which loads in instance methods this.


Compare: Java Tutorials - Inner Class Example

Upvotes: 2

Adrian Szymański
Adrian Szymański

Reputation: 11

When you call the callInner method, you are actually within the scope of Outer class. And the reason, why the compiler accepts calling new Inner() is exactly the same, why you don't have to write explicitly what class your some imagined static variable comes from (when it's the part of the same class you call it). See example below:

public class Outer {
  private static int x = 1;

  private void innerCall() {
    x++;
  }
}

In above case, you do exactly the same as in your example with exception, that you use the class and not the variable (which is not really relevant in here). Your syntax would be necessary if wanted to access the class/variable from the outside of the class (scope). It would then look like the thing below:

public class Outer {
  public static int x = 1;
}

Outer.x++;

Above, you have to explicitly specify what scope you want to access your variable x from. It's just like you wanted to access the file from within the given directory. If you're in this directory, you just access the file by it's name. However, when you are outside of it, you have to write also the directory's name to see the file you want to get.

Upvotes: 1

GauravRai1512
GauravRai1512

Reputation: 844

First main method will be called

public static void main(String[] args){
        Outer out = new Outer();
        out.callInner();
}

from here you have create an object of Outer class and called callInner method like below

public void callInner() {
        Inner in = new Inner(); //in my opinion the correct constructor is Outer.Inner in = new Inner()
        in.go();
    }

and now you have created an object of Inner and called go method.

 protected class Inner {
        public int repeat=3;

        public void go() {
            for (int i =0; i<repeat; i++) {
                System.out.println(greeting);
            }
        }
    }

so it's a simple call all are in a same scope. so need for outer.Inner concept to call.

It's important to understand that Outer and Inner are related. More specifically, you need an Outer instance in order to create an Inner instance.

Upvotes: 2

Eamon Scullion
Eamon Scullion

Reputation: 1384

As you are instantiating Inner within the scope of Outer (inside an instance method), you do not need to explicitly instantiate referencing the Outer clas, like in your example:

Outer.Inner in = new Outer().new Inner();

It is fine to instantiate by just referencing Inner:

 Inner in = new Inner();

This applies to all instance methods within a class, as long as they are not static.

Upvotes: 7

Related Questions