0

I'm reading the source code of ArrayList and this class has an inner class with the name SubList. I'm looking in a method of the inner class (SubList) and see the following methods:

 public E set(int index, E e) {
        rangeCheck(index);
        checkForComodification();
        E oldValue = ArrayList.this.elementData(offset + index);
        ArrayList.this.elementData[offset + index] = e;
        return oldValue;
    }

What I see that line 3 & 4 uses this keyword in order to call/use ArrayList (outer class) method/attribute. I want to understand is it must to use OuterClass.this or elementData() will be enough? I run an example long ago (more than a year) and I was able to call an outer class method from an inner class without using this keyword.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Eitanos30
  • 1,331
  • 11
  • 19
  • 2
    It doesn't have to use `ArrayList.this`, but at least to me, that's more readable. – Sweeper Mar 29 '22 at 19:19
  • 3
    For members that are in both the inner and outer class, you have to qualify with `Outer.this` if you want the outer member. This happens most frequently with methods like `Object::equals`, and also frequently happens in various decorator/proxy/combinator situations. – Brian Goetz Mar 31 '22 at 01:00

1 Answers1

4

There is a Shadowing problem that can lead to unexpected behavior and runtime errors.

If a declaration of a type (such as a member variable or a parameter name or method name) in a particular scope (such as an inner class or a method definition) has the same name as another declaration in the enclosing scope, then the declaration shadows the declaration of the enclosing scope. You cannot refer to a shadowed declaration by its name alone.

public class ShadowTest {

    public int x = 0;

    class FirstLevel {

        public int x = 1;

        void methodInFirstLevel(int x) {
            System.out.println("x = " + x);
            System.out.println("this.x = " + this.x);
            System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
        }
    }

    public static void main(String... args) {
        ShadowTest st = new ShadowTest();
        ShadowTest.FirstLevel fl = st.new FirstLevel();
        fl.methodInFirstLevel(23);
    }
}

Output:

x = 23
this.x = 1
ShadowTest.this.x = 0

As you can see, to get the correct value of higher scope, you need to use only ShadowTest.this.

Thru time your code will mutate and you can miss the same name in the other scope, so you must use only OuterClass.this to access outer class scope, make code clear and bulletproof.

See the Java Tutorial.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Eugene
  • 5,269
  • 2
  • 14
  • 22