简体   繁体   中英

Accessing outer class from inner class in java

I know about inner class and nested class from Java inner class and static nested class

But can any body tell me what's the difference between Inner.redo1() and Inner.redo2()?

Or Inner.print1() and Inner.print2() are the same?

public class Outer {
    private String str = "outer";
    public void print() {
      System.out.println("a");
    }

    public class Inner {
        public void redo1() {
            print();
        }
        public void redo2() {
            Outer.this.print();
        }
    }
}

PS: In java.util.ArrayList.Itr#remove

public void remove() {
    if (lastRet < 0)
        throw new IllegalStateException();
    checkForComodification();

    try {
        ArrayList.this.remove(lastRet);
        cursor = lastRet;
        lastRet = -1;
        expectedModCount = modCount;
    } catch (IndexOutOfBoundsException ex) {
        throw new ConcurrentModificationException();
    }
}

Why does it use ArrayList.this.remove(lastRet); but not remove(lastRet); ?

But can any body tell me what's the difference between Inner.redo1() and Inner.redo2()?

Inner.redo1() and Inner.redo2() are indeed the same. There is no semantic or functional difference. redo2 is more explicit. That is all.

Let's compare each method's bytecode:

λ  Desktop  javap -c Outer.Inner
Compiled from "Outer.java"
public class Outer$Inner extends java.lang.Object{
final Outer this$0;

public Outer$Inner(Outer);
  Code:
   0:   aload_0
   1:   aload_1
   2:   putfield    #1; //Field this$0:LOuter;
   5:   aload_0
   6:   invokespecial   #2; //Method java/lang/Object."<init>":()V
   9:   return

public void redo1();
  Code:
   0:   aload_0
   1:   getfield    #1; //Field this$0:LOuter;
   4:   invokevirtual   #3; //Method Outer.print:()V
   7:   return

public void redo2();
  Code:
   0:   aload_0
   1:   getfield    #1; //Field this$0:LOuter;
   4:   invokevirtual   #3; //Method Outer.print:()V
   7:   return

}

Same bytecode, same end result, same everything.


Why does it use ArrayList.this.remove(lastRet); but not remove(lastRet); ?

To disambiguate which class' remove() method should actually be called. It is actually necessary in this case! Without explicitly specifying ArrayList.this.remove(lastRet) , the code does not compile:

λ  Desktop  javac java/util/ArrayList.java
java/util/ArrayList.java:810: remove() in java.util.ArrayList<E>.Itr cannot be applied to (int)
                remove(lastRet);
                ^
1 error
  1. In your example, they are the same. But if there is a significant difference between the inner instance and the outer instance that will affect the result of print(), then that's when they will be different.

  2. ArrayList.this.remove(lastRet) refers to the ArrayList (outer class) instance using remove(). remove(lastRet) will instead make the instance of whatever inner class it is, to use the remove() method.

"So the rules for an inner class referencing itself or the outer instance are as follows:

■ To reference the inner class instance itself, from within the inner class code, use this.

■ To reference the "outer this" (the outer class instance) from within the inner class code. "

-from SCJP 6 by Kathy Sierra and Bert Bates

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM