静态内部类不持外部类引用,创建更快、更轻量;非静态内部类隐式持有this$0引用,导致内存开销与gc问题,且只能访问外部类static成员。

静态内部类不用持外部类引用,创建更快、更轻量
静态内部类(static class)在加载时完全独立于外部类实例,JVM 不会为它隐式注入 this$0 字段——那个指向外围对象的引用。这意味着:
- 创建
Outer.StaticInner实例时,不需要先 newOuter() - 每个
StaticInner对象不额外携带外部类对象的内存开销(通常省下 4–8 字节引用空间) - GC 更友好:即使外部类对象已不可达,静态内部类实例仍可安全存活
反观非静态内部类(即成员内部类),每次 new 出来都悄悄绑着一个 this$0,哪怕你根本没访问外部类字段——这是编译器强制加的,躲不掉。
非静态内部类能访问所有外部成员,但代价是强耦合
它能直接读写 private int x、调用 void helper(),甚至用 Outer.this.x 显式访问同名字段。这种便利背后是硬绑定:
- 无法单独序列化非静态内部类(会抛
java.io.NotSerializableException,除非外部类也序列化) - 不能在静态上下文(如
static方法、静态代码块)中直接 new 它,必须依赖外部类实例 - 若外部类持有大对象(比如
byte[]或缓存 Map),内部类实例会间接阻止其回收
示例:new Outer().new Inner() 合法;new Outer.Inner() 编译报错:「no enclosing instance」。
经过一段时间的开发,以及内部测试,同程网联盟景区新版程序正式发布推出,感谢广大联盟会员一直以来的支持与关注! 同程网联盟景区新版程序新功能介绍:1.统一的页面风格。页面风格将与随后推出的度假线路、酒店、机票以及融合版联盟程序风格保持一直;2.新增后台管理系统。可更加方便快捷的对网站进行个性化设置;3.动态与伪静态切换。后台操作,简单便捷;4.缓存管理。新增缓存,提高网站访问速度,后台可定期清理;5
静态内部类只能访问外部类的 static 成员
这是最常踩的坑:你以为能用 outerField,结果编译失败。
- 静态内部类中,直接写
outerInstanceVar→ 报错non-static variable cannot be referenced from a static context - 想访问非静态成员?必须显式 new 外部类:
new Outer().instanceMethod()或new Outer().instanceField - 但注意:这会创建新对象,不是原外部类实例——别误以为在“共享状态”
而静态成员(public static final String TAG、private static int COUNTER)可直接用,无需实例。
选哪个?看是否需要“看到外面的世界”
判断依据非常实在:
- 只做工具类、DTO、Builder、枚举辅助类?→ 用
static class(比如Map.Entry就是静态内部类) - 要响应外部类事件、修改外部类字段、实现监听器回调?→ 必须用非静态内部类(如 Android 的
RecyclerView.Adapter子类常这么用) - 不确定?先写成静态的;编译报错说“无法访问非静态成员”,再改——比事后排查内存泄漏简单得多
真正容易被忽略的是:非静态内部类在匿名场景(比如 new Thread(() -> {...}))中极易造成意外的长生命周期引用,尤其在 Activity 或 Fragment 中——这点比语法差异更致命。







