Skip to main content

Advanced Java

Inner Classes & Lambdas

Complete lesson for Inner Classes & Lambdas using LEARNCODEGURU’s 6-level learning model — from basics to advanced practice, with Java OOP and Collections where relevant.

L1

Basics — Inner Classes & Lambdas

Section: Advanced Java. Inner, static nested, local, and anonymous classes — plus lambdas and method references.

Four nested types

  • **Static nested class:** like a top-level class namespaced inside another. No hidden outer this. Prefer this when you do not need the outer instance.
  • **Inner class (non-static):** holds Outer.this. new Outer().new Inner().
  • **Local class:** declared inside a method. Can see effectively final locals.
  • **Anonymous class:** new Interface() { ... } — one-off implementation. Lambdas replaced many of these.
TypeOuter instance?Typical use
Static nestedNoBuilder, Entry, helpers
InnerYesIterator that walks outer fields
LocalIf in instance methodRare, named one-off
AnonymousSame as localListeners (pre-lambda)

Lambdas

  • A lambda implements a **functional interface**: (args) -> expression or (args) -> { statements; }.
  • Captured local variables must be **final or effectively final** (not reassigned).
  • Lambdas do not create a new named type you write, but they still compile to classes/methods behind the scenes (invokedynamic).
import java.util.Arrays;
import java.util.List;

public class LambdaBasics {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("neo", "ada", "linus");
        names.sort((a, b) -> a.length() - b.length());
        names.forEach(System.out::println);
    }
}

Method references

  • System.out::println is x -> System.out.println(x).
  • Kinds: static (Integer::parseInt), instance on a target (list::add), instance on an unbound type (String::toLowerCase), constructor (ArrayList::new).
L2

Advanced — Inner Classes & Lambdas

this, serialization, and when not to lambda

  • Inside a lambda, this is the *enclosing* class, not the lambda. Inside an anonymous class, this is the anonymous instance.
  • A non-static inner class cannot have static members (except compile-time constants) in older Java; Java 16 relaxed some static nested rules — interviews still say “inner class has a hidden outer reference”.
  • Do not use a lambda if you need multiple methods, a meaningful this, or a constructor. Use a named class.
  • Comparator.comparing(User::name) plus .thenComparing is the Java 8+ sort idiom.
L3

Tricky Interview Points

Q1) Inner class vs static nested class?

Answer Inner (non-static) holds a reference to the outer instance. Static nested does not and can be constructed without an outer object.

Q2) Why must captured locals be effectively final?

Answer The lambda may outlive the stack frame. Java copies the local; allowing reassignment would make the copy and the variable diverge.

Q3) Lambda vs anonymous class?

Answer Lambda is shorter, this is the outer class, and it targets a SAM. Anonymous class can implement many methods and declare state.

Q4) How do you instantiate an inner class from outside?

Answer new Outer().new Inner() — you need an outer instance.

Q5) What is a method reference?

Answer A compact lambda that only calls an existing method: Class::method or obj::method.

Q6) Can an interface have a lambda if it has default methods?

Answer Yes, as long as there is exactly one abstract method.

L4

Simple Programs

Static nested class and a lambda filter

import java.util.ArrayList;
import java.util.List;

public class NestedDemo {
    static class Pair {
        final String key;
        final int value;

        Pair(String key, int value) {
            this.key = key;
            this.value = value;
        }
    }

    public static void main(String[] args) {
        List<Pair> pairs = new ArrayList<>();
        pairs.add(new Pair("a", 1));
        pairs.add(new Pair("b", 5));
        pairs.removeIf(p -> p.value < 3);
        pairs.forEach(p -> System.out.println(p.key + "=" + p.value));
    }
}
L5

Problem Solving Tricks

  • Default to static nested. Only make it inner when you truly need the outer instance.
  • If a lambda is more than a few lines, extract a method and use a method reference.
  • Do not shadow variables named x just to make (x) -> look clever — use domain names.
  • removeIf, forEach, replaceAll on collections are the everyday lambda APIs.
L6

Practice Programs List

  1. Write an inner Iterator-style class that walks an int[] stored on the outer instance.
  2. Convert that inner class to static nested by passing the array in.
  3. Sort a List with a lambda and again with String::compareToIgnoreCase.
  4. Show that reassigning a local used in a lambda is a compile error.
  5. Replace an anonymous Runnable with a lambda and then with this::instanceMethod.