Java内部类编译后生成独立.class文件,命名规则为“外部类名$内部类名”或“外部类名$数字”;成员内部类含this$0字段,静态内部类无此字段,局部及匿名类以数字编号。

Java 内部类在字节码层面不是“语法糖”,而是实实在在生成独立 .class 文件的实体。编译器对每种内部类都有一套明确、可预测的命名规则,这些名字直接暴露了它的类型身份和运行时行为特征。
成员内部类的命名与字节码特征
编译后生成 外部类名$内部类名.class,比如 Outer$Inner.class。
这个文件里藏着关键线索:
- 编译器自动添加了一个隐式字段
Outer this$0,指向外围实例; - 构造器被重写为带
Outer类型参数的形式(哪怕源码里没写); - 它无法脱离外部类实例单独存在——这是字节码强制约定,不是语言规范限制。
静态内部类的命名看似相同,但本质不同
同样叫 Outer$StaticInner.class,但它:
- 没有
this$0字段; - 构造器不接收外部类引用;
- 常量池中不包含对外部类非静态成员的符号引用;
- 可以像普通顶级类一样直接
new Outer.StaticInner()实例化。
局部内部类和匿名内部类靠数字编号区分
定义在方法或代码块里的局部类,编译后变成 Outer$1.class 或 Outer$1Local.class(JDK 版本不同略有差异);
匿名内部类统一用纯数字,如 Outer$1.class、Outer$2.class。
它们共同特点是:
- 会把所在方法中用到的局部变量“捕获”为构造器参数,并存为 final 字段;
- 如果访问了外部类字段,也会通过隐式参数传入外围实例(成员局部类)或仅传静态字段(静态上下文中的局部类)。
嵌套多层时命名是线性展开的
比如 Outer 里有 Inner,Inner 里再定义 Nested,就生成 Outer$Inner$Nested.class;
这种命名天然反映作用域链,也方便类加载器按 $ 拆解归属关系。


















