Aren’t Anonymous Inner Classes actually subclasses?



Assume that A is a custom class, and consider the following declaration of an anonymous inner class:

A Obj = new A() {
    @Override
    public String toString() {
        return "Hello!";
    }
}

In this scenario, Obj is an instance of an anonymous inner class whose toString method has been overridden. Since it was declared with type A, the anonymous class must be a subclass of A. So then, why isn’t this class called an Anonymous Subclass instead of an anonymous inner class? Where does the ‘inner’ come from?

Answer

To answer your question’s title, yes, they are. Anonymous inner classes are actually subclasses.

“Since it was declared with type A, the anonymous class, [Obj], must be a subclass of A.”

Good job. 🙂

Anyways, to answer why the “inner” is there: If you declare an anonymous class inside another class (and the anonymous class isn’t declared statically, more on that below) then it would be able to access its surrounding class just like an inner class would. For example:

public class Outer {
    private final int someRandomValue = 4;

    public final Object anonymousInnerInstance = new Object() {
        @Override
        public String toString() {
            // Notice how this class has access to a field declared inside a different
            // class. More specifically, this anonymous class can access someRandomValue,
            // even though someRandomValue belongs to the class, Outer.
            return "Anonymous Inner Class: " + someRandomValue;
        }
    };

    public class RegularInner {
        @Override
        public String toString() {
            // This regular inner class is inside Outer, (just like the anonymous class),
            // and can access any of Outer's fields (amongst Outer's other things).
            return "Regular Inner Class: " + someRandomValue;
        }
    }

    public final RegularInner regularInnerInstance = new RegularInner();

    public static void main(String[] args) {
        Outer outerInstance = new Outer();
        System.out.println(outerInstance.anonymousInnerInstance);
        System.out.println(outerInstance.regularInnerInstance);

        // By the way, you can make new RegularInner instances off of our Outer
        // instance:
        RegularInner newInnerInstance = outerInstance.new RegularInner();
        // When you write "outerInstance.new SomeClass()" you're saying:
        // "I'd like to initialize my 'SomeClass' object with 'outerInstance',
        // as its container." This effectively means that any variables that
        // belong to Outer that your SomeClass needs to access, it will access
        // from the Outer instance you gave it.
    }
}

So, anonymousInnerInstance‘s underlying class, and the class RegularInner, both have access to Outer‘s fields, and other instance-specific content belonging to Outer. That’s why an anonymous class may sometimes be called an “inner” class.

Any instance of an inner class needs to be created with an instance of an outer class to back it up, or it won’t know which object, (not class), it belongs to.


Static Trash

If an anonymous class is declared as static, it won’t have access to its surrounding class’s content and wouldn’t be an “inner” class (instead, it would be an anonymous “nested” class).

public class Outer {
    private final int someRandomValue = 4;

    public static final Object anonymousStaticInstance = new Object() {
        @Override
        public String toString() {
            // someRandomValue belongs to an INSTANCE of Outer. (So each Outer object you
            // have has its own someRandomValue). Since this anonymous class
            // is now static, it is no longer tied to an instance of Outer. It doesn't have
            // an Outer object that it can read "someRandomValue" from. The same goes for
            // RegularStatic, below.
            return "Anonymous Inner Class: " + someRandomValue;
        }
    };

    public static class RegularStatic {
        @Override
        public String toString() {
            return "Regular Inner Class: " + someRandomValue;
        }
    }

    public final RegularStatic regularInnerInstance = new RegularStatic();

    public static void main(String[] args) {
        Outer outerInstance = new Outer();
        System.out.println(outerInstance.anonymousStaticInstance);// Java warns you here and
        // tells you to access anonymousStaticInstance statically. This is because
        // anonymousStaticInstance no longer belongs to any given instance of Outer.
        // There is only one anonymousStaticInstance, that "belongs" to the class Outer,
        // rather than multiple anonymousInnerInstances which each belong to an instance
        // of Outer.
        System.out.println(outerInstance.regularInnerInstance);
    }
}

Remember that anonymous classes can be “inner” OR “nested”. So when talking about them in general, just say “anonymous class”. (Anonymous inner classes are a type of anonymous class). Also, do make sure to read the comments as they give most of the explanation.

Any questions? 🙂



Source: stackoverflow