Nested Interface in Java – Interfaces Inside Classes and Interfaces
A nested interface (also called an inner interface) is an interface declared inside a class or another interface. It groups an interface with the type it belongs to, so the relationship is obvious from the name, as in Map.Entry or Button.ClickListener.
This tutorial covers nested interfaces inside classes and inside interfaces, their implicit modifiers and access rules, and when to use them.
1. What Is a Nested Interface?
class Outer {
interface Inner { ... } // nested in a class: any access modifier allowed
}
interface OuterInterface {
interface Inner { ... } // nested in an interface: always public static
}
class Impl implements Outer.Inner { ... } // refer to it as Outer.Inner
Nested interfaces are always implicitly static: they do not belong to an instance of the outer type, so there is no "inner interface object" tied to an outer object.
2. Nested Interface Inside a Class
A common use is a callback type that belongs to a component, like a click listener of a button:
public class NestedInClass {
static class Button {
// Nested interface: belongs logically to Button (implicitly static)
public interface ClickListener {
void onClick(String buttonLabel);
}
private final String label;
private ClickListener listener;
Button(String label) { this.label = label; }
void setOnClickListener(ClickListener listener) { this.listener = listener; }
void click() { if (listener != null) listener.onClick(label); }
}
// A class implementing the nested interface uses Outer.Inner as the name
static class Logger implements Button.ClickListener {
public void onClick(String buttonLabel) { System.out.println("LOG: '" + buttonLabel + "' clicked"); }
}
public static void main(String[] args) {
Button save = new Button("Save");
save.setOnClickListener(new Logger());
save.click();
Button cancel = new Button("Cancel");
cancel.setOnClickListener(label -> System.out.println("Lambda: " + label + " pressed"));
cancel.click();
}
}
LOG: 'Save' clicked Lambda: Cancel pressed
The name Button.ClickListener clearly says "the listener type for buttons". Because it has a single abstract method, it is also a functional interface and accepts a lambda.
3. Nested Interface Inside an Interface
An interface can define a related interface, such as the entry type of a container. The JDK's Map.Entry is the best-known example:
import java.util.Map;
import java.util.TreeMap;
public class NestedInInterface {
interface Cache {
// Nested interface inside an interface: implicitly public static
interface Entry {
String key();
int hits();
}
void put(String key);
Iterable<? extends Entry> entries();
}
static class SimpleCache implements Cache {
record Item(String key, int hits) implements Cache.Entry { }
private final Map<String, Integer> data = new TreeMap<>();
public void put(String key) { data.merge(key, 1, Integer::sum); }
public Iterable<Item> entries() {
return data.entrySet().stream().map(e -> new Item(e.getKey(), e.getValue())).toList();
}
}
public static void main(String[] args) {
Cache cache = new SimpleCache();
for (String k : new String[] {"java", "spring", "java", "kafka", "java"}) cache.put(k);
for (Cache.Entry e : cache.entries()) System.out.println(e.key() + " -> " + e.hits());
// The JDK's best-known nested interface: Map.Entry
Map<String, Integer> scores = Map.of("Asha", 91);
for (Map.Entry<String, Integer> e : scores.entrySet())
System.out.println("Map.Entry: " + e.getKey() + "=" + e.getValue());
}
}
java -> 3 kafka -> 1 spring -> 1 Map.Entry: Asha=91
4. Rules and Modifiers
| Declared inside | Allowed access modifiers | Implicit modifiers |
|---|---|---|
| A class | public, protected, package-private, private | static |
| An interface | public only | public static |
- A nested interface is referenced as
Outer.Inner, or imported directly (import java.util.Map.Entry;). - Implementing the outer class or interface does not require implementing its nested interface, and vice versa.
- A
privatenested interface can be implemented only within the outer class, which is useful for internal strategies. - Since Java 16, interfaces (and records and enums) can also be declared as local types inside a method body.
5. Nested Interfaces in the JDK
Map.Entry<K, V>: a key-value pair in a map.Thread.UncaughtExceptionHandler: handles exceptions that end a thread.Thread.Builder(Java 21): builds platform and virtual threads.java.net.http.HttpResponse.BodyHandler: decides how to process an HTTP response body.
6. When to Use Nested Interfaces
- The interface only makes sense together with the outer type (callbacks, entries, handlers).
- You want to keep the package namespace clean and the relationship explicit.
- You want to restrict visibility, for example a
privateinterface used only inside one class.
If the interface is useful on its own, in many unrelated places, a top-level interface is clearer.
7. Summary
- A nested interface is declared inside a class or interface and referred to as
Outer.Inner. - Nested interfaces are implicitly static.
- Inside an interface they are always public; inside a class they can have any access level.
- They group closely related types, as in
Map.Entryand listener interfaces.
Related Tutorials
Frequently Asked Questions (FAQ)
Q1. What is a nested interface in Java?
An interface declared inside a class or another interface, used to group types that belong together logically.
Q2. Are nested interfaces static?
Yes. They are implicitly static, whether or not you write the keyword.
Q3. Can a nested interface be private?
Yes, if it is declared inside a class. Inside an interface it is always public.
Q4. How do I implement a nested interface?
Use its qualified name: class Logger implements Button.ClickListener { ... }, or import it and use the simple name.
Q5. What is an example of a nested interface in Java?
Map.Entry, the interface for key-value pairs inside the Map interface.
Q6. Does implementing the outer interface require implementing the nested one?
No. They are independent types; the nesting is only a naming and access relationship.
Q7. Can a nested interface be protected?
Yes, when declared inside a class. It is then accessible in the same package and in subclasses.
Q8. Why use a nested interface instead of a top-level one?
To show that it belongs to the outer type, keep the package namespace tidy, and optionally restrict its visibility.
Q9. Can a nested interface have default and static methods?
Yes. It is a normal interface in every respect except its location and access rules.
Q10. Can a nested interface be a functional interface?
Yes. If it has exactly one abstract method, it can be implemented with a lambda, as many listener interfaces are.
Q11. Can I import a nested interface?
Yes: import java.util.Map.Entry; lets you write Entry<K, V> instead of Map.Entry<K, V>.
Q12. Can an interface contain a class?
Yes. Classes, records and enums nested in an interface are implicitly public and static.
Q13. Is there an inner interface that is not static?
No. Unlike inner classes, interfaces are never tied to an outer instance, so all member interfaces are static.
Q14. Can an interface be declared inside a method?
Yes, since Java 16. Local interfaces are implicitly static and cannot capture local variables.
Q15. What is the compiled file name of a nested interface?
Outer$Inner.class, for example Map$Entry.class.
Q16. Can a nested interface access private members of the outer class?
Its default and static methods can access the outer class's private static members, because nested types share access with their enclosing type.
Q17. Can a nested interface extend the outer interface?
Yes. It is legal, though uncommon, for a nested interface to extend its enclosing interface.
Q18. Is Thread.UncaughtExceptionHandler a nested interface?
Yes. It is declared inside the Thread class and handles exceptions that terminate a thread.
Q19. Can a class implement both the outer and nested interface?
Yes: class X implements Outer, Outer.Inner is valid if it implements the methods of both.
Q20. Are nested interfaces common in modern code?
Yes, especially for callbacks, builders and entry types, and in sealed hierarchies where related types are grouped in one file.