Inner, static nested and anonymous classes

Sometimes a class only makes sense inside another one: a bill belongs to a shop, a seat belongs to a train, a one-off discount rule is needed in just one method. Java lets you declare classes inside classes: inner classes tied to an outer object, static nested classes that are just grouped, local classes inside a method, and anonymous classes written and used in one expression. You'll learn all four, what each can see, and what javac quietly adds to make them work.

Module 10 · Core Classes⏱ 24 minIntermediate8 practice problems
1 The story

A bill that knows its shop

Riya is writing billing software for a chain of chai stalls. Every Bill needs the stall's name and GST number on top. She has been passing the Shop object into every bill by hand, and twice she passed the wrong shop.

Shop object: "Chai Point, Kharghar" Bill #101₹120this$0 → Bill #102₹45this$0 → static class Taxgst(amount)needs no shop object new Discount() { apply(p) {…} } a one-off rule, no name myphatshala.in
Riya

Sir, every bill needs its shop's name. I keep passing the shop in, and sometimes it's the wrong shop.

Arjun Sir

Then make Bill an inner class of Shop. You create a bill from a shop: shop.new Bill(120). Each bill then remembers its shop automatically and can read the shop's fields, even private ones.

Riya

And the GST calculation? It doesn't need any particular shop.

Arjun Sir

That's a static nested class: grouped inside Shop for neatness, but with no link to a shop object. And for the festival discount used in just one place, you don't even need a name: an anonymous class, written right where you use it.

2 Definition

What are nested classes?

Formal definition (write this in exams)

A nested class is a class declared inside another class or interface. A static nested class is declared with static and is not tied to an instance of the outer class. A non-static nested class is an inner class; there are three kinds: a member inner class (declared at class level), a local class (declared inside a block such as a method) and an anonymous class (declared and instantiated in a single expression, without a name). Every inner class instance holds an implicit reference to an instance of its enclosing class, and inner classes can access the enclosing class's members, including private ones. Local and anonymous classes may use local variables of the enclosing block only if they are final or effectively final.

In simple words

A class written inside another class. If it's static, it's just stored there. If it isn't, each of its objects belongs to an outer object and can use that object's data. Anonymous classes are quick, nameless classes for one-time use.

Words you'll meet in this lesson

Outer (enclosing) classThe class that contains the nested class.
Enclosing instanceThe outer object an inner object belongs to.
this$0The hidden field javac adds to an inner class to hold the enclosing instance.
Outer.thisHow code in an inner class names its outer object explicitly.
Effectively finalA local variable never changed after it's set, even without the word final.
CaptureWhen a local or anonymous class copies a local variable's value to use later.

The four kinds at a glance

KindDeclaredCreate withOuter object?Class file
Member innerin the class bodyshop.new Bill()Yes, requiredShop$Bill.class
Static nestedin the class body, staticnew Shop.Tax()NoShop$Tax.class
Localinside a method/blocknew Receipt() in that blockYes, if the method isn't staticShop$1Receipt.class
Anonymousin an expressionnew Discount() { … }Yes, if in instance codeShop$1.class

Exam tip: a static nested class is not an inner class. It can't use the outer class's instance fields directly (non-static variable cannot be referenced from a static context). An inner class object can't exist without an outer object, so new Inner() inside a static method fails; write outer.new Inner().

3 Types and ways to use it

The four kinds, with code

Member inner

Belongs to an outer object; reads its fields. A bill of a shop, a seat of a train.

has this$0

Static nested

Just grouped inside the outer class. Helpers, builders, map entries.

no outer object

Local

Declared inside a method, visible only there.

rare

Anonymous

No name; implements an interface or extends a class in one expression.

one-off behaviour

1. Member inner class

class Shop {
    private final String name;

    Shop(String name) { this.name = name; }

    class Bill {                                // inner: no 'static'
        int amount;
        Bill(int amount) { this.amount = amount; }

        String print() {
            return name + ": ₹" + amount;       // reads the outer object's private field
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Shop kharghar = new Shop("Chai Point, Kharghar");
        Shop vashi = new Shop("Chai Point, Vashi");

        Shop.Bill b1 = kharghar.new Bill(120);  // a bill OF the Kharghar shop
        Shop.Bill b2 = vashi.new Bill(45);
        System.out.println(b1.print());
        System.out.println(b2.print());
    }
}
Chai Point, Kharghar: ₹120 Chai Point, Vashi: ₹45

Behind the scenes javac gives Bill a hidden field final Shop this$0 and passes the outer object into its constructor. Here is javap -p on a similar class (JDK 21):

class Bank$Account {
  int bal;
  final Bank this$0;          ← the link to the outer object
  Bank$Account(Bank);         ← the constructor receives it
  int interest();
  java.lang.String bank();
}

2. Static nested class

class Shop {
    static class Tax {                         // static: no Shop object needed
        static int gst(int amount) {
            return amount * 5 / 100;
        }
    }

    static class Address {
        final String city, pin;
        Address(String city, String pin) { this.city = city; this.pin = pin; }
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(Shop.Tax.gst(120));
        Shop.Address a = new Shop.Address("Navi Mumbai", "410210");   // no shop object
        System.out.println(a.city + " " + a.pin);
    }
}
6 Navi Mumbai 410210

3. Local class

public class Main {
    static void printReceipt(String customer, int amount) {
        class Line {                               // visible only inside this method
            String text(String label, int value) {
                return label + " for " + customer + ": ₹" + value;   // uses a captured local
            }
        }
        Line l = new Line();
        System.out.println(l.text("Amount", amount));
        System.out.println(l.text("GST", amount * 5 / 100));
    }

    public static void main(String[] args) {
        printReceipt("Riya", 200);
    }
}
Amount for Riya: ₹200 GST for Riya: ₹10

4. Anonymous class

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

interface Discount {
    int apply(int price);
}

public class Main {
    public static void main(String[] args) {
        Discount festive = new Discount() {        // class with no name, created at once
            public int apply(int price) {
                return price - price / 10;         // 10% off
            }
        };
        System.out.println(festive.apply(500));

        List<String> names = new ArrayList<>(List.of("Riya", "Kabir", "Om"));
        names.sort(new Comparator<String>() {     // a one-off sort rule
            public int compare(String a, String b) {
                return a.length() - b.length();
            }
        });
        System.out.println(names);
    }
}
450 [Om, Riya, Kabir]

Since Java 8, an anonymous class implementing an interface with a single abstract method is usually written as a lambda: p -> p - p / 10 (Lesson 14.1). Anonymous classes are still needed when you extend a class, implement several methods, or need fields.

Captured variables must be effectively final

int off = 50;
off = 60;                                          // now 'off' changes...
Discount d = new Discount() {
    public int apply(int p) { return p - off; }    // error
};
error: local variables referenced from an inner class must be final or effectively final

The anonymous object copies the value of off into a hidden field (val$off) when it's created. If the local could change later, the copy and the original would disagree, so Java forbids it.

Which one? Start with a static nested class: it's simpler and holds no hidden reference. Make it an inner class only if each object truly needs its outer object. Use anonymous classes (or lambdas) for short, one-place behaviour, and a normal top-level class when other files need it.

4 Step by step

What happens on shop.new Bill(120)

  1. javac compiles two classes

    From one Shop.java, javac writes Shop.class and Shop$Bill.class. To the JVM, an inner class is an ordinary class with a $ in its name; Java 11+ records them as “nestmates” so they can share private members.
  2. The constructor gets an extra argument

    Shop.Bill b = kharghar.new Bill(120);
    // compiled roughly as: new Shop$Bill(kharghar, 120)
    javac passes the outer object as a hidden first argument. If kharghar were null, this line would throw NullPointerException.
  3. The link is stored in this$0

    The constructor saves it in the synthetic field final Shop this$0. The Bill object on the heap now points to its Shop object.
  4. Reading an outer field goes through the link

    return name + ": ₹" + amount;   // really: this$0.name + ": ₹" + this.amount
    Each use of an outer field compiles to a read through this$0. If both classes have a field with the same name, write Shop.this.name to mean the outer one.
  5. The link keeps the outer object alive

    As long as any Bill is reachable, its Shop can't be garbage-collected (Lesson 8.3). A long-lived inner object (for example a listener stored in a static list) can therefore leak a large outer object. Static nested classes don't have this problem.
5 See it happen

Inner vs static nested: both views

Left: the code. Right: the objects on the heap, including the hidden link an inner object keeps to its outer object.

The hidden link from inner to outer 6 steps
What you see Shop k = new Shop("Kharghar"); Shop.Bill b1 = k.new Bill(120); Shop.Bill b2 = k.new Bill(45); println(b1.print()); println(Shop.Tax.gst(120)); k = null; Console Kharghar: ₹120 Kharghar: ₹120 6 An ordinary object. A bill created FROM the shop. A second bill from the same shop. The bill prints its shop's name. No object needed for Tax. We drop our shop variable. myphatshala.in
Behind the screen Stack (main) Heap k → b1 → b2 → k null Shop name "Kharghar" Bill amount 120 this$0 → Bill amount 45 this$0 → this$0.name → "Kharghar" Tax.gst(120): no object created Shop still reachable via this$0 One Shop object on the heap. Bill gets a hidden this$0 link to its shop. Both bills point to the same shop. print() reads name through this$0. Static nested: a plain static call. The bills keep the shop alive. myphatshala.in
6 Real-world use

Nested classes in real systems

You use nested classes every day in the JDK and in frameworks, often without noticing the $ in their names.

Watch it with an example: sorting a cricket leaderboard

A turf-cricket app sorts batters by runs using an anonymous Comparator. Watch the list ask the anonymous object to compare pairs.

An anonymous Comparator at work 5 steps
Animated example list.sort(new Comparator<Player>() { compare(a, b) { return b.runs - a.runs; } }); Om34 runs Riya71 runs Kabir12 runs Main$1 (anonymous) object compare(Riya, Om) = 34 − 71 < 0 → Riya first compare(Kabir, Om) = 34 − 12 > 0 → Kabir after Om compare(Kabir, Riya) = 71 − 12 > 0 → stays last waiting to be asked… sorted: Riya 71, Om 34, Kabir 12 myphatshala.in
HashMapstatic Node

1. Data structure internals

HashMap keeps its entries in a static nested class HashMap.Node; LinkedList has LinkedList.Node; ArrayList's iterator is the inner class ArrayList.Itr, which reads the list's private array through its outer link.

list.iterator()→new Itr() (inner)→reads the outer list
Order.builder() .item(..).build()

2. Builders

Classes with many optional fields often expose a static class Builder nested inside them: new Pizza.Builder().size(LARGE).cheese().build(). The builder is grouped with the class it builds but needs no existing object.

new Order.Builder()→static nested→build() → Order
PayonClick(…)

3. Event handlers and callbacks

Desktop and Android apps attach click listeners as anonymous classes (now usually lambdas). Thread code passes a new Runnable() { … }. Each is a small piece of behaviour written exactly where it's used.

button→new OnClickListener() { … }→runs on tap
leak

4. Memory leaks to watch for

An inner-class listener registered with a long-lived service keeps its outer object (say a whole screen with images) in memory through this$0. Android guidelines recommend static nested classes for such cases.

static registry→inner listener → this$0→outer object can't be freed

Examples are simplified. JDK class names and internals vary between versions.

7 Run the code

A chai stall with bills, tax and a festival offer

interface Offer {
    int apply(int amount);
}

class Stall {
    private final String name;
    private int billCount = 0;

    Stall(String name) { this.name = name; }

    class Bill {                                    // inner: belongs to one stall
        final int no;
        final int amount;

        Bill(int amount) {
            this.amount = amount;
            billCount++;                            // updates the OUTER object's field
            this.no = billCount;
        }

        String print(Offer offer) {
            int pay = offer.apply(amount);
            return name + " #" + no + ": ₹" + pay + " + GST ₹" + Tax.gst(pay);
        }
    }

    static class Tax {                              // static nested: no stall needed
        static int gst(int amount) { return amount * 5 / 100; }
    }
}

public class Main {
    public static void main(String[] args) {
        Stall s = new Stall("Chai Point");
        Offer diwali = new Offer() {                // anonymous class
            public int apply(int amount) { return amount >= 100 ? amount - 20 : amount; }
        };
        Stall.Bill b1 = s.new Bill(120);
        Stall.Bill b2 = s.new Bill(60);
        System.out.println(b1.print(diwali));
        System.out.println(b2.print(diwali));
    }
}
Chai Point #1: ₹100 + GST ₹5 Chai Point #2: ₹60 + GST ₹3
  • class BillInner class: every bill is created from a stall and reads its name.
  • billCount++An inner object can change the outer object's private field: both bills share one counter.
  • static class TaxStatic nested: called as Tax.gst(…), no stall object required.
  • new Offer() { … }Anonymous class implementing Offer, written where it's used.
8 Line by line

The hidden link, recorded from the JVM

This trace is recorded from the real JVM. Look at the inner Bill object on the heap: besides amount it has a field this$0 pointing to the outer object. The static nested Tax call needs no object at all.

Worked examples: real problems, solved and traced in memory

Three designs using each kind of nested class. Watch the heap for this$0 and val$…: the hidden fields javac adds.

Example 1Railways · inner class

Seats that know their train

Problem statement

A Train books seats. Each Seat must print its label as 12123/S4-32 using the train's number, and every booking increases the train's booked count.

Input
Train "12123": book S4-32, S4-33
Expected output
12123/S4-32, 12123/S4-33 | booked 2

Approach

  1. Make Seat a member inner class, so each seat is tied to one train.
  2. The Seat constructor increments the outer booked field.
  3. label() reads the outer number through the hidden link.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

Example 2Restaurant · anonymous class

A one-off alert format that captures a variable

Problem statement

A kitchen screen needs alerts prefixed with the outlet name, like [Chai Point] Order #12 ready. Write the formatter as an anonymous class of interface Alert, using a local variable for the outlet name.

Input
outlet "Chai Point", events "Order #12 ready", "Order #13 ready"
Expected output
[Chai Point] Order #12 ready
[Chai Point] Order #13 ready

Approach

  1. Declare the outlet name as a local variable; it stays effectively final.
  2. Create new Alert() { … }: javac copies the local into the anonymous object (hidden field val$outlet).
  3. Call format for each event.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

Example 3Food delivery · static nested

An order built step by step

Problem statement

An Order has a customer, an item and optional extras (express delivery, cutlery). Use a static nested Builder so callers can't mix up the arguments, and print the final bill.

Input
Riya, Masala Dosa ₹120, express (+₹30)
Expected output
Riya pays ₹150

Approach

  1. Order has a private constructor that takes a Builder.
  2. static class Builder collects values with named methods, each returning this.
  3. build() creates the immutable Order.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

9 Quiz and revision

Check yourself

Quick revision

Lesson 10.5 in one screen

  • Nested = class inside a class. Static nested (no outer object) vs inner (member, local, anonymous).
  • Member inner: outer.new Inner(); holds hidden this$0; can read outer private members; Outer.this.x for name clashes.
  • Static nested: new Outer.Nested(); can't use outer instance fields; preferred when no outer object is needed.
  • Local class: inside a method, visible only there.
  • Anonymous: new Interface() { … }; one use; files Outer$1.class. Often replaced by lambdas.
  • Captured locals must be final or effectively final (copied into val$x).
  • Class files: Outer$Inner, Outer$1, Outer$1Local. Inner objects keep outer objects alive.

Interview and viva questions

What is the difference between a static nested class and an inner class?

A static nested class is like a top-level class placed inside another for grouping; it has no reference to an outer object and is created with new Outer.Nested(). An inner class instance is tied to an outer instance (hidden this$0), can use its instance members directly, and is created with outer.new Inner().

Can an inner class access private members of the outer class?

Yes, and the outer class can access the inner class's private members too. Before Java 11, javac generated hidden accessor methods (access$000) for this; since Java 11 the JVM knows they are nestmates and allows it directly.

Anonymous class vs lambda?

A lambda can only implement a functional interface (one abstract method) and has no state of its own; this inside a lambda means the enclosing object. An anonymous class can extend a class, implement several methods, have fields, and its this is the anonymous object itself. Lambdas don't create a $1.class file per use; they're linked at run time (invokedynamic).

Why are captured variables required to be effectively final?

Local variables live on the stack and disappear when the method returns, but the inner object may live longer. So Java copies the value into the object. If the local could change afterwards, the copy would be stale and confusing, so the language forbids changing it.

Can a nested class be private or static? Can a top-level class?

Nested classes can use any access modifier (private, protected, …) and static. Top-level classes can only be public or package-private and can't be static (Lesson 6.5).

Practice problems

Choose the right kind of nested class and use each one correctly. The last three are business tasks.

P1Easy

Create an inner object

Class College has an inner class Student that prints the college name with the student's name. Create one from main.

Input
College "GES", student "Riya"
Expected output
Riya @ GES Law College
Show solution and explanation
class College {
    private final String name;
    College(String name) { this.name = name; }

    class Student {
        final String sname;
        Student(String sname) { this.sname = sname; }
        String card() { return sname + " @ " + name; }
    }
}

public class Main {
    public static void main(String[] args) {
        College c = new College("GES Law College");
        College.Student s = c.new Student("Riya");
        System.out.println(s.card());
    }
}
Riya @ GES Law College

How it works: c.new Student(...) ties the student to college c; card() reads the outer name.

P2Easy

Use a static nested helper

Put a static nested class Units inside Converter with a method kmToMiles. Convert 42 km.

Input
42 km
Expected output
26.10 miles
Show solution and explanation
class Converter {
    static class Units {
        static double kmToMiles(double km) { return km * 0.621371; }
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.printf("%.2f miles%n", Converter.Units.kmToMiles(42));
    }
}
26.10 miles

How it works: a static nested class is reached through the outer class name; no objects are needed.

P3Easy

An anonymous greeting

Implement interface Greeter { String greet(String n); } with an anonymous class that returns Namaste, <name>!.

Input
"Kabir"
Expected output
Namaste, Kabir!
Main$1
Show solution and explanation
interface Greeter {
    String greet(String n);
}

public class Main {
    public static void main(String[] args) {
        Greeter g = new Greeter() {
            public String greet(String n) { return "Namaste, " + n + "!"; }
        };
        System.out.println(g.greet("Kabir"));
        System.out.println(g.getClass().getName());
    }
}
Namaste, Kabir! Main$1

How it works: the anonymous class has no source name; javac calls it Main$1, which getClass().getName() shows.

P4Medium

Outer.this for clashing names

Both Account and its inner class Statement have a field id. Print both from inside Statement.

Input
account id 501, statement id 9
Expected output
Account 501, statement 9
Show solution and explanation
class Account {
    int id = 501;

    class Statement {
        int id = 9;
        String header() {
            return "Account " + Account.this.id + ", statement " + id;
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Account a = new Account();
        System.out.println(a.new Statement().header());
    }
}
Account 501, statement 9

How it works: plain id is the nearest one (Statement's); Account.this.id names the outer object's field.

P5Medium

Local class with a captured variable

In a method report(String month, int[] sales), declare a local class that formats each line using month. Print two lines.

Input
"Oct", {1200, 950}
Expected output
Oct week 1: ₹1200
Oct week 2: ₹950
Show solution and explanation
public class Main {
    static void report(String month, int[] sales) {
        class Line {
            String text(int week, int amount) {
                return month + " week " + week + ": ₹" + amount;
            }
        }
        Line l = new Line();
        for (int i = 0; i < sales.length; i++) {
            System.out.println(l.text(i + 1, sales[i]));
        }
    }

    public static void main(String[] args) {
        report("Oct", new int[]{1200, 950});
    }
}
Oct week 1: ₹1200 Oct week 2: ₹950

How it works: month is effectively final, so the local class may capture it. The class exists only inside report.

P6Business problem

Discount rules as anonymous classes

Apply two discount rules to ₹800: a flat ₹50 off and 15% off. Implement each rule as an anonymous class of interface Rule and print the better price.

Input
₹800
Expected output
Flat: ₹750, 15%: ₹680 → best ₹680
Show solution and explanation
interface Rule {
    int apply(int price);
}

public class Main {
    public static void main(String[] args) {
        Rule flat = new Rule() {
            public int apply(int price) { return price - 50; }
        };
        Rule percent = new Rule() {
            public int apply(int price) { return price - price * 15 / 100; }
        };
        int a = flat.apply(800), b = percent.apply(800);
        System.out.println("Flat: ₹" + a + ", 15%: ₹" + b + " → best ₹" + Math.min(a, b));
    }
}
Flat: ₹750, 15%: ₹680 → best ₹680

How it works: two anonymous classes (Main$1, Main$2) implement the same interface differently. Callers just call apply.

P7Business problem

Bank account with an inner transaction log

A Wallet keeps a list of Txn objects. Txn is an inner class whose constructor updates the wallet's balance. Add ₹500, spend ₹120, and print the balance and log size.

Input
+500, -120
Expected output
Balance ₹380, 2 transactions
Show solution and explanation
import java.util.ArrayList;
import java.util.List;

class Wallet {
    private int balance = 0;
    private final List<Txn> log = new ArrayList<>();

    class Txn {
        final int amount;
        Txn(int amount) {
            this.amount = amount;
            balance += amount;          // outer field
            log.add(this);              // outer list
        }
    }

    void add(int amt) { new Txn(amt); }
    void spend(int amt) { new Txn(-amt); }
    String summary() { return "Balance ₹" + balance + ", " + log.size() + " transactions"; }
}

public class Main {
    public static void main(String[] args) {
        Wallet w = new Wallet();
        w.add(500);
        w.spend(120);
        System.out.println(w.summary());
    }
}
Balance ₹380, 2 transactions

How it works: inside Wallet's own methods, new Txn(...) uses this as the outer object automatically. Each transaction updates the balance and logs itself.

P8Business problem

Pizza order builder

Build a large pizza with extra cheese using a static nested Builder. Medium costs ₹249, large ₹399, extra cheese ₹40.

Input
large + cheese
Expected output
Large pizza: ₹439
Show solution and explanation
class Pizza {
    final String size;
    final int price;

    private Pizza(Builder b) {
        this.size = b.size;
        this.price = b.price;
    }

    static class Builder {
        private String size = "Medium";
        private int price = 249;

        Builder large() { size = "Large"; price = 399; return this; }
        Builder cheese() { price += 40; return this; }
        Pizza build() { return new Pizza(this); }
    }
}

public class Main {
    public static void main(String[] args) {
        Pizza p = new Pizza.Builder().large().cheese().build();
        System.out.println(p.size + " pizza: ₹" + p.price);
    }
}
Large pizza: ₹439

How it works: the static nested builder can call Pizza's private constructor. Chained methods make each choice readable, and the Pizza itself is immutable.

Real-world scenario questions (asked in company interviews)

Nested-class questions test design judgement: should this class know about its outer object, and what does that link cost?

Mobile app · memoryJunior

A screen that never leaves memory

After users open and close the “Order history” screen many times, the app runs out of memory. A heap dump shows dozens of screen objects kept alive by a listener list in a singleton service. The listeners are inner classes of the screen. Explain and fix.

The interviewer is checking: the hidden this$0 reference and its effect on GC.

Show a strong answer
  • Each inner listener holds this$0 → the screen. The singleton's list is reachable forever, so every screen (with its views and images) stays reachable.
  • Unregister listeners when the screen closes.
  • Make the listener a static nested class that holds only what it needs (or a weak reference to the screen).
  • Verify with a heap dump before and after.

Avoid: calling System.gc(). The objects are still reachable, so GC can't free them.

Library designFresher

Where should Node live?

You're writing your own LinkedList with a Node class. Should Node be a top-level class, an inner class, or a static nested class?

The interviewer is checking: choosing the right nesting.

Show a strong answer
  • Private static nested: Node is an implementation detail (so nested and private) and doesn't need the list object (so static).
  • An inner Node would waste a this$0 reference per node: memory multiplied by every element.
  • The JDK does exactly this: private static class Node<E> in java.util.LinkedList.

Avoid: making it public top-level “in case someone needs it”. That freezes your internals into your API.

Backend · refactoringJunior

Twenty anonymous comparators

A reporting module sorts lists with 20 copies of new Comparator<Order>() { … }, many identical. How would you clean this up?

The interviewer is checking: when anonymous classes stop being a good idea.

Show a strong answer
  • Replace each with a lambda or Comparator.comparing(Order::getAmount) (Lessons 11.8 and 14.1); one line instead of five.
  • Put reusable rules in one place: static final Comparator<Order> BY_AMOUNT in the Order class.
  • Each anonymous class also generates a separate .class file; fewer, shared comparators are easier to test.

Avoid: leaving duplicated logic because “it works”. Duplicates drift apart over time.

Fintech · APIMid

A payment request with eleven optional fields

The PaymentRequest constructor has 11 parameters, and callers keep mixing up the order of amount and fee. What pattern would you use, and how does nesting help?

The interviewer is checking: the builder pattern with a static nested class.

Show a strong answer
  • A static nested Builder: PaymentRequest.builder().amount(500).fee(5).upi("riya@okbank").build(). Named methods make each value obvious.
  • The builder is nested so it can call the private constructor and stays grouped with the class it builds; it's static because no request exists yet.
  • build() validates required fields, and the resulting object can be immutable.

Avoid: setters on the request itself. A half-filled, mutable payment object is a bug waiting to happen.