Java
inner class
outer class
object-oriented programming
programming tutorial

How to access outer class from an inner class?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Java, a non-static inner class holds an implicit reference to its enclosing (outer) class instance. You access the outer class using OuterClass.this. Static nested classes do not have this reference and require an explicit parameter. Python and C# handle inner-to-outer access differently — Python has no implicit reference, and C# only supports static nested types.

Java: Non-Static Inner Class

A non-static inner class automatically gets a reference to the outer class instance that created it:

java
1public class Outer {
2    private String name = "OuterInstance";
3    private int count = 42;
4
5    public class Inner {
6        private String name = "InnerInstance";
7
8        public void showOuter() {
9            // Access outer class field directly
10            System.out.println(count);  // 42
11
12            // Disambiguate when names conflict
13            System.out.println(this.name);        // "InnerInstance"
14            System.out.println(Outer.this.name);   // "OuterInstance"
15        }
16
17        public Outer getOuter() {
18            return Outer.this;  // Returns the enclosing instance
19        }
20    }
21}
22
23// Usage — inner class needs an outer instance
24Outer outer = new Outer();
25Outer.Inner inner = outer.new Inner();
26inner.showOuter();

Outer.this is the syntax for accessing the enclosing instance. Without name conflicts, you can access outer fields directly.

Java: Static Nested Class

Static nested classes have no implicit outer reference:

java
1public class Outer {
2    private int value = 10;
3
4    public static class StaticNested {
5        public void tryAccess() {
6            // System.out.println(value);  // COMPILE ERROR — no outer reference
7            // System.out.println(Outer.this);  // COMPILE ERROR
8        }
9
10        public void accessViaParameter(Outer outer) {
11            System.out.println(outer.value);  // Works — explicit reference
12        }
13    }
14}
15
16// No outer instance needed
17Outer.StaticNested nested = new Outer.StaticNested();
18nested.accessViaParameter(new Outer());

Static nested classes are just regular classes scoped inside another class. Use them when the inner class does not need the outer instance.

Java: Passing Outer Reference Explicitly

When you need outer access from a static context or want explicit control:

java
1public class Outer {
2    private String data = "secret";
3
4    public class Worker {
5        public void process() {
6            // Implicit access via Outer.this
7            System.out.println(Outer.this.data);
8        }
9    }
10
11    // Alternative: pass explicitly
12    public static class ExplicitWorker {
13        private final Outer outer;
14
15        public ExplicitWorker(Outer outer) {
16            this.outer = outer;
17        }
18
19        public void process() {
20            System.out.println(outer.data);
21        }
22    }
23}

Explicit passing is preferred in modern Java — it makes the dependency clear and avoids the hidden reference.

Java: Anonymous Inner Classes

Anonymous inner classes also capture the outer instance:

java
1public class Button {
2    private String label = "Submit";
3
4    public void addClickHandler() {
5        ActionListener listener = new ActionListener() {
6            @Override
7            public void actionPerformed(ActionEvent e) {
8                // Accesses outer field directly
9                System.out.println("Clicked: " + label);
10                // Or explicitly: Button.this.label
11            }
12        };
13    }
14}

Lambdas (Java 8+) also capture the enclosing instance but do not create a separate this:

java
1public void addClickHandler() {
2    ActionListener listener = e -> {
3        System.out.println("Clicked: " + label);
4        // 'this' here refers to Button, not the lambda
5    };
6}

Python

Python classes do not have an implicit outer reference. Pass it explicitly:

python
1class Outer:
2    def __init__(self):
3        self.data = "outer_data"
4
5    class Inner:
6        def __init__(self, outer):
7            self.outer = outer
8
9        def show(self):
10            print(self.outer.data)
11
12outer = Outer()
13inner = Outer.Inner(outer)
14inner.show()  # "outer_data"

Python's inner classes are just classes defined inside another class's scope. There is no Outer.this equivalent — you must pass the reference manually.

C#

C# only supports static nested classes (no implicit outer reference):

csharp
1public class Outer
2{
3    private string _data = "hello";
4
5    // All nested classes in C# are like Java's static nested classes
6    public class Inner
7    {
8        private readonly Outer _outer;
9
10        public Inner(Outer outer)
11        {
12            _outer = outer;
13        }
14
15        public void Show()
16        {
17            Console.WriteLine(_outer._data);  // Access via explicit reference
18        }
19    }
20}
21
22var outer = new Outer();
23var inner = new Outer.Inner(outer);
24inner.Show();

Kotlin

Kotlin uses this@Outer syntax (inner classes must be marked with the inner keyword):

kotlin
1class Outer {
2    val name = "OuterInstance"
3
4    inner class Inner {
5        val name = "InnerInstance"
6
7        fun show() {
8            println(this.name)           // "InnerInstance"
9            println(this@Outer.name)     // "OuterInstance"
10        }
11    }
12}
13
14val inner = Outer().Inner()
15inner.show()

Without the inner keyword, Kotlin nested classes are static by default (no outer reference).

Common Pitfalls

  • Memory leaks from inner class references: Non-static inner classes hold a strong reference to the outer instance. In Android, an inner AsyncTask or Handler in an Activity prevents the Activity from being garbage collected. Use static nested classes with WeakReference instead.
  • Serialization issues: Serializing a non-static inner class also serializes the outer instance (because of the implicit reference). This can fail or produce unexpectedly large serialized objects.
  • Confusing this in anonymous classes: Inside an anonymous inner class, this refers to the anonymous class, not the enclosing class. Use OuterClass.this to access the enclosing instance.
  • Assuming Python has implicit outer access: Python nested classes have no implicit reference to the enclosing instance. Always pass the outer reference as a constructor parameter.
  • Using non-static when static suffices: If the inner class does not need the outer instance, make it static (static class Inner in Java, remove inner in Kotlin). This avoids unnecessary memory overhead and potential leaks.

Summary

  • Java non-static inner classes access the outer instance via OuterClass.this
  • Java static nested classes have no outer reference — pass it explicitly if needed
  • Python has no implicit outer reference — always pass the enclosing instance manually
  • C# only supports the equivalent of Java's static nested classes
  • Kotlin uses this@Outer syntax and requires the inner keyword for non-static inner classes
  • Prefer static nested classes to avoid memory leaks and hidden dependencies

Course illustration
Course illustration

All Rights Reserved.