Course topics

By WebNest Studio Engineering Team

Java - Core Tutorial

Nested Interfaces in Java

A nested interface is an interface declared inside a class or inside another interface, rather than as its own top-level file. Java allows this because interfaces, like classes, can be members of another type. Nested interfaces are a common pattern for grouping a helper interface tightly with the one class (or interface) that logically owns it.

Why it matters

A nested interface is an interface declared inside a class or another interface, used when it only makes sense in that context. You use one every time you loop over a map: Map.Entry. The same pattern appears in callback and listener APIs, so recognising the Outer.Inner name is part of reading library code.

Why Nest an Interface

Nesting communicates intent: "this interface only makes sense in the context of its enclosing type." A frequent real example is a listener or callback interface — a class that fires events defines a nested interface describing how outsiders should react to those events, keeping the contract physically next to the class that uses it. This avoids cluttering the package with small, tightly-coupled interfaces that are meaningless anywhere else.

Rules for Nested Interfaces

A nested interface is implicitly static when declared inside a class (even without writing the keyword), meaning it does not depend on any instance of the enclosing class to be referenced or implemented. It can carry any access modifier (public, protected, default, private since Java 9 for interface members) that a regular class member can. It is referenced from outside using the enclosing type's name as a qualifier.

  • Declared inside a class: OuterClass.NestedInterface is how you refer to it from elsewhere.
  • Declared inside another interface: it behaves the same way, qualified by the enclosing interface's name.
  • A class can implement a nested interface just like any top-level interface: class Impl implements OuterClass.NestedInterface { ... }.

Example

A nested Listener interface used for a simple event callback pattern

Java
class Button {

    // Nested interface: tightly coupled to Button, only meaningful here
    interface ClickListener {
        void onClick(String buttonName);
    }

    private String name;
    private ClickListener listener;

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

    void setClickListener(ClickListener listener) {
        this.listener = listener;
    }

    void simulateClick() {
        if (listener != null) {
            listener.onClick(name);
        }
    }
}

public class NestedInterfaceDemo implements Button.ClickListener {

    @Override
    public void onClick(String buttonName) {
        System.out.println(buttonName + " was clicked!");
    }

    public static void main(String[] args) {
        Button submitButton = new Button("Submit");
        NestedInterfaceDemo handler = new NestedInterfaceDemo();

        submitButton.setClickListener(handler);   // referenced via Button.ClickListener
        submitButton.simulateClick();
    }
}
Output
Submit was clicked!

Common Mistakes

  • Forgetting to qualify the nested interface with its enclosing type name when referencing it from outside (writing "ClickListener" instead of "Button.ClickListener").
  • Assuming a nested interface needs an instance of the outer class to be implemented — nested interfaces are implicitly static and independent of any outer instance.
  • Overusing nested interfaces for contracts that are actually general-purpose and used across many unrelated classes — those belong as top-level interfaces instead.
  • Confusing a nested interface with an anonymous inner class that implements an interface — they solve different problems (defining a contract vs providing an implementation).

Exercise

Loop over the entries of the map and print each one as key=value, using the nested interface Map.Entry.

Expected output: apple=3 then banana=5

Java · starter code
import java.util.Map;
import java.util.TreeMap;

public class EntryLoop {
    public static void main(String[] args) {
        Map<String, Integer> stock = new TreeMap<>();
        stock.put("banana", 5);
        stock.put("apple", 3);

        // TODO: loop over stock.entrySet() and print key=value for each entry
    }
}
Show hints
  • Each element of entrySet() has the type Map.Entry<String, Integer>.
  • An entry gives you getKey() and getValue(). A TreeMap iterates in key order.
Show solution
Java · solution
import java.util.Map;
import java.util.TreeMap;

public class EntryLoop {
    public static void main(String[] args) {
        Map<String, Integer> stock = new TreeMap<>();
        stock.put("banana", 5);
        stock.put("apple", 3);

        for (Map.Entry<String, Integer> entry : stock.entrySet()) {
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
    }
}

Quick quiz

1. An interface declared inside another interface is implicitly what?

  • A. private
  • B. abstract and final
  • C. protected
  • D. public and static
Show answer

D. Members of an interface are public, and a nested interface is always static.

2. Which of these is a well-known nested interface in the JDK?

  • A. Map.Entry
  • B. Runnable
  • C. Comparable
  • D. Serializable
Show answer

A. Entry is declared inside the Map interface and represents one key-value pair.

3. A class Button declares a nested interface Listener. How does another class refer to it?

  • A. Listener.Button
  • B. Button.Listener
  • C. Button::Listener
  • D. Button->Listener
Show answer

B. A nested type is referred to through its enclosing type with a dot: Button.Listener.

Interview questions

Why would you nest an interface inside a class or another interface?

Show answer

To show that it belongs to that type and has no meaning on its own. Map.Entry only makes sense as part of a map, and a Button.Listener only as a callback for that button. Nesting groups related types, keeps the top-level namespace smaller, and makes the relationship obvious from the name.

Key Points to Remember

  • A nested interface is declared inside a class or another interface to signal a tight logical coupling.
  • Nested interfaces declared inside a class are implicitly static and do not require an outer instance.
  • Reference them from outside using OuterType.NestedInterface syntax.
  • A very common real-world use is defining listener/callback contracts alongside the class that fires the events.

Practice in the playground

Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.

Run the examples

Change an input, predict the result, then compare it with the output. Explain why the result changes.

WebNest Studio

Written by

WebNest Studio Engineering Team

Practical lessons from developers working with Java, Python, React, databases and production systems.

Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering