Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A Java inner class is a nested class that is not explicitly or implicitly declared static. When declared in an instance context, an inner class maintains a hidden, implicit reference to the specific instance of its enclosing class. This relationship grants the inner class direct access to all members (fields and methods) of the enclosing class, regardless of their access modifiers, including private. However, if a local or anonymous inner class is declared within a static context (such as a static method or static initializer), it does not have an enclosing instance and therefore does not maintain this implicit reference.

Types of Inner Classes

The Java Language Specification defines three distinct types of inner classes based on their declaration context.

1. Member Inner Class

Declared at the class level of the enclosing class, outside of any method or block. It acts as a standard member of the outer class and can be assigned standard access modifiers (public, protected, private, or package-private). Because a member inner class is tied to an instance of the outer class, its instantiation from outside the outer class requires an existing outer instance and uses the outerInstance.new Inner() syntax. Internally, the inner class accesses the outer class instance using the qualified this keyword (OuterClass.this).
public class OuterMember {
    private String outerField = "Outer State";

    public class MemberInner {
        public void printState() {
            // Direct access to private outer member
            System.out.println(outerField);
            
            // Explicitly referencing the outer instance via qualified 'this'
            System.out.println(OuterMember.this.outerField);
        }
    }
}

class Main {
    public static void main(String[] args) {
        // Instantiation syntax requires an outer instance for member inner classes
        OuterMember outerInstance = new OuterMember();
        OuterMember.MemberInner innerInstance = outerInstance.new MemberInner();
    }
}

2. Local Inner Class

A named nested class declared within a block, typically inside a method body, constructor, or initialization block. Its scope is strictly restricted to the block in which it is defined. It is instantiated directly using the new keyword within that block, rather than using the outerInstance.new syntax. A local inner class can access the members of its enclosing class (provided it is not in a static context), as well as local variables of the enclosing block, provided those local variables are final or effectively final (assigned only once and never mutated).
public class OuterLocal {
    public void execute() {
        int effectivelyFinalVar = 42; 

        // Local inner class declaration
        class LocalInner {
            public void readVars() {
                // Accesses the local variable from the enclosing method
                System.out.println(effectivelyFinalVar);
            }
        }

        // Instantiated directly within the block
        LocalInner local = new LocalInner();
        local.readVars();
    }

    public static void staticExecute() {
        // Local inner class in a static context (no enclosing instance)
        class StaticContextLocal {
            public void print() {
                System.out.println("No implicit outer reference exists here.");
            }
        }
        new StaticContextLocal().print();
    }
}

3. Anonymous Inner Class

An unnamed inner class defined and instantiated in a single expression. It is a distinct type of inner class, not a subset of local classes, because it lacks an identifier. It must either extend an existing class or implement an interface. Because it has no name, it cannot define explicit constructors; instead, it relies on instance initializer blocks for complex setup. Like local classes, it is instantiated directly at the site of its declaration and does not use the outerInstance.new syntax.
public class OuterAnonymous {
    public void createRunnable() {
        // Declaration and instantiation of an anonymous inner class
        Runnable r = new Runnable() {
            // Instance initializer block (substitute for constructor)
            {
                System.out.println("Anonymous instance created");
            }

            @Override
            public void run() {
                System.out.println("Anonymous execution");
            }
        };
        r.run();
    }
}

Variable Shadowing

If a declaration of a variable in an inner class shares the exact identifier as a variable in the enclosing scope, the inner declaration shadows the outer declaration. To bypass the shadow and access the outer member, the code must use the qualified this syntax. This technique is only applicable if the inner class is declared in an instance context.
public class ShadowingOuter {
    private int value = 1;

    public class ShadowingInner {
        private int value = 2;

        public void printValues() {
            System.out.println(value);                     // Resolves to 2 (Inner scope)
            System.out.println(this.value);                // Resolves to 2 (Inner scope)
            System.out.println(ShadowingOuter.this.value); // Resolves to 1 (Outer scope)
        }
    }
}
Master Java with Deep Grasping Methodology!Learn More