嵌套类是定义在另一个类内部的类。Java 有四种 — 静态嵌套类、内部类(非静态)、局部类和匿名类 — 每种对封闭类的访问方式不同,使用场景也不同。
1. 静态嵌套类 — 独立于实例
java
{
;
{
{
System.out.println(data);
}
}
}
Outer. .Nested();
static 嵌套类的行为像一个顶级类,但被命名空间化在外部类内。它不持有外部实例的引用 — 用于对帮助类进行分组(例如 Builder、数据结构中的 Node)。
public class Outer {
private int value = 5;
class Inner { // non-static → has an implicit reference to Outer
void show() {
System.out.println(value); // can access Outer's INSTANCE members (even private)
}
}
}
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // needs an Outer instance to create
非静态内部类隐式持有其封闭实例的引用,因此可以访问外部对象的实例字段。(警告:如果内部实例比外部实例存活更久,这个引用可能导致内存泄漏。)
void process() {
class Helper { // local to this method
void run() { ... }
}
new Helper().run();
}
很少使用;作用域限定在方法内。
// implement an interface/abstract class inline, for single use
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { handleClick(); }
});
Runnable task = new Runnable() {
public void run() { System.out.println("running"); }
};
匿名类是接口或类的一次性实现,在定义和实例化的同时进行 — 历史上常用于事件处理器和回调。现代 Java 在目标是函数式接口时通常用 lambdas 替代:
button.addActionListener(e -> handleClick()); // ✅ lambda — much cleaner
Runnable task = () -> System.out.println("running");
嵌套类是一个有用的工具,用于逻辑地分组仅在一个上下文中使用的类,提高封装性和可读性。
理解这些种类 — 特别是 static 与 inner 的区别(static = 独立,inner = 持有封闭实例引用)— 对设计和避免 bug 都很重要:内部类的隐式外部引用可能导致内存泄漏,而在不需要外部实例时选择 static 是更清晰的做法。
匿名类是提供内联实现(事件处理器、比较器)的经典方式,了解它们在很大程度上被函数式接口的 lambdas 所取代,反映了现代 Java 的使用能力。
这些在标准库中随处可见(例如 Map.Entry 是嵌套接口,builders 是静态嵌套类),使它们成为实用的、频繁遇到的知识。