skip to content

Nested vs inner Classes

A nested class in Kotlin is static by default; adding inner is what gives it a reference to the outer instance, reachable via this@Outer. This is exactly inverted from Java, which is why it comes up so often.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

In Kotlin, what is the difference between a class declared inside another class with no modifier versus one declared with the `inner` keyword?

level: juniorimportance: must knowfreq 70%

answer

  1. No keyword = static-like nested
  2. inner keyword = holds outer reference
  3. Outer.Nested() vs outer.Inner()
  4. Kotlin default is opposite of Java
  5. Only inner can see outer's instance members

basics

~20 s

By default a class inside another class is nested and standalone: it does not know about the outer object. Adding the inner keyword links it to an outer instance, so it can use the outer object's data.

solid answer

~30 s

A class nested inside another with no modifier is a nested class. It is conceptually 'static': it holds no reference to an instance of the outer class and cannot access the outer's non-static (instance) members. You create it with `Outer.Nested()`. Marking it `inner` makes it an inner class: each instance carries an implicit reference to an enclosing `Outer` instance, so it can read the outer's instance properties/methods. You must create it from an outer instance: `outer.Inner()`. Kotlin defaults to nested (the opposite of Java, where inner is the default), which avoids accidental outer references and the memory leaks they cause.

code

kotlin · 9 lines
kotlin
class Outer {
    private val secret = 42
    class Nested { fun show() = "nested" }
    inner class Inner { fun show() = "secret=$secret" }
}
fun main() {
    println(Outer.Nested().show())   // nested
    println(Outer().Inner().show())  // secret=42
}

go deeper

for a junior

Knows that plain nesting is static-like and inner adds an outer reference, and can state the two construction syntaxes.

for a middle

Explains why nested can't see outer members and recalls that Kotlin's default is the inverse of Java's.

for a senior

Connects the default to memory-leak avoidance and reasons about when capturing the outer is actually desirable.

for a principal

Frames the default as a deliberate language design choice trading away Java compatibility for safer-by-default semantics, and weighs API/encapsulation implications.

## The two kinds Kotlin lets you declare a class inside another class. The modifier (or absence of one) controls whether it captures the enclosing object. - **Nested class** (no modifier): standalone. It does **not** hold a reference to an `Outer` instance and **cannot** touch the outer's instance members. Equivalent to a `static` nested class in Java. - **Inner class** (`inner` keyword): every instance holds an implicit reference to the `Outer` instance that created it, and can access the outer's instance members. ## Construction differs ```kotlin class Outer { private val secret = 42 class Nested { // static-like fun show() = "nested" // cannot see `secret` } inner class Inner { // holds Outer reference fun show() = "secret=$secret" // CAN see `secret` } } val n = Outer.Nested() // no Outer instance needed val i = Outer().Inner() // needs an Outer instance ``` ## Why Kotlin defaults to nested Java's default is the opposite: a non-`static` inner class captures the outer instance, which silently keeps it alive and is a classic source of memory leaks (e.g. an inner `Runnable` keeping an Activity alive on Android). Kotlin flips the default to the safer one: you only pay for an outer reference when you explicitly write `inner`. ## Key takeaways - No keyword = nested = no outer reference. - `inner` = captures outer instance, can use `this@Outer`. - Nested: `Outer.Nested()`; inner: `outerInstance.Inner()`.

  • If you forget `inner` and try to reference an outer instance property from the body, what happens?
    It does not compile: a nested class has no access to the outer's instance members, so the reference is unresolved.
  • Why is Kotlin's default safer than Java's?
    Java captures the outer instance by default, which can leak memory; Kotlin only captures when you opt in with `inner`.

A nested class is a tenant who shares the building's address but has no key to the landlord's apartment; an inner class is given that key.

saying these in an interview costs you the question

  • Saying nested classes can access outer instance members
  • Claiming you create a nested class via an outer instance like `outer.Nested()`
  • Stating Kotlin's default matches Java's (it is the opposite)
  • Confusing `inner` with `internal` (visibility)
  • Thinking `inner` is required for any nesting

context

open as a page

Inside an inner class, how do you access the outer class instance, and how do you disambiguate `this` when names collide between inner and outer?

level: middleimportance: must knowfreq 60%

basics

~20 s

Use a labeled this: this@Outer refers to the outer object and this@Inner (or just this) to the inner one. This lets you pick the right object when both define a property or method with the same name.

open as a page

Why can declaring `inner` on a nested class cause memory leaks, and how does choosing nested instead help?

level: middleimportance: should knowfreq 45%

basics

~20 s

An inner class secretly holds a reference to its outer object, so as long as the inner instance is alive, the outer can't be garbage-collected. A plain nested class holds no such reference, so it lets the outer be freed.

open as a page

How do nested vs inner classes interact with generics and interface implementations on the outer class? For example, can a nested class implement an interface using the outer's type parameter?

level: seniorimportance: should knowfreq 30%

basics

~20 s

A nested class is independent, so it cannot use the outer class's type parameters or instance state. An inner class can, because it is tied to a specific outer instance and shares its generic context.

open as a page

What does the compiler actually generate for nested vs inner classes, and how should that inform your default choice when designing an API?

level: principalimportance: nice to knowfreq 20%

basics

~20 s

A nested class compiles to a standalone (static-like) class with no link to the outer. An inner class compiles to a class with a hidden field pointing at the outer object. Default to nested and only add inner when you truly need that link.

open as a page