Search code examples
javaclassinner-classesinstance-methods

Why am I throwing no errors for calling object-specific methods/fields from inner classes?


I'm using something similar to the following code in one of my Java classes:

public class SomeClass {
    private int someValue;

    void incrementValue() {
        someValue++;
    }

    public abstract static class InnerClass {
        private final SomeClass toRunOn;

        public InnerClass(SomeClass obj) {
            toRunOn = obj;
        }

        public abstract void execute();

        // To allow us to call this on a given instance
        final SomeClass getObj() {
            return toRunOn;
        }
    }

    public final InnerClass called = new InnerClass(this) {
        public final void execute() {
            incrementValue(); // This is what I thought should be throwing an error
        }
    };
}

However, while I would expect this to throw a compiler error in the called field defining execute() due to me not giving incrementValue() an object to work on (which is why I allowed for passing this to the inner class), it is completely fine with it. I'm uncertain why this is not giving me an error, and further confused as to what instance it would be calling on.

Am I misunderstanding some form of reference calling here, or is something more subtle going on?


Solution

  • called is assigned an instance of an anonymous sub-class of InnerClass. Since it's an instance member, it is initialized when an instance of SomeClass is created.

    Since it is declared in the body of SomeClass, it is an inner class of SomeClass and has access to the instance methods and members of SomeClass. incrementValue() will be executed on the instance of SomeClass for which the called member was initialized.

    Perhaps it would be easier to understand if you replace the anonymous class with an equivalent regular inner class :

    public class SomeClass {
    
        ....
    
        class SubInnerClass extends InnerClass {
            public final void execute() {
                incrementValue();
            }
        }
    
        public final InnerClass called = new SubInnerClass(this);
    
        ....
    }