核心区别是静态内部类不持外部类实例引用,非静态内部类隐式持有this$0引用;前者可直接new Outer.StaticInner()、访问外部static成员、定义静态成员,后者须通过Outer().new Inner()创建、可访问所有外部成员但影响GC且禁止非final静态成员。

核心就一条:静态内部类不持有外部类实例引用,非静态内部类会隐式持有一个 this$0 引用,绑定到创建它的那个外部类对象。
创建方式完全不同
静态内部类像普通顶层类一样直接构造:
-
new Outer.StaticInner()—— 不需要先有Outer实例 - 编译后是独立的
Outer$StaticInner.class,和外部类实例无关联
非静态内部类必须依托外部类对象:
-
new Outer().new Inner()—— 先 new 外部类,再用它 new 内部类 -
new Outer.Inner()会编译报错:“no enclosing instance”
能不能访问外部类成员,取决于有没有 this
静态内部类没有隐式外部类引用:
- 能直接使用
Outer.staticField、Outer.staticMethod() - 写
instanceField或调instanceMethod()直接编译失败 - 真要访问实例成员?只能手动
new Outer().xxx—— 但这不是原对象,也不共享状态
非静态内部类自带隐式 this$0:
- 可直接读写
private int x、调用void helper(),哪怕没显式写Outer.this.x - 即使代码里一句没用外部成员,
this$0依然存在——占内存、影响 GC
能不能定义静态成员,暴露本质差异
静态内部类本身就是“类级别”的:
- 可以声明
public static final String TAG - 也能写
private static int counter = 0、static void init() {}
非静态内部类生来依附于实例:
- 除
static final编译期常量外,其他静态字段或方法一律禁止 - 因为它的存在前提就是有外部对象,和“静态”语义冲突
选哪个,看你要不要“看到外面的世界”
只做工具类、DTO、Builder、缓存辅助?→ 优先静态内部类
要响应事件、修改外部字段、实现监听器回调?→ 必须非静态内部类
不确定?先写 static,编译报错说“无法访问非静态成员”,再改——比事后查内存泄漏省力得多

















