java内部类编译后均生成独立.class文件,命名统一为“外部类名$标识符”:成员内部类如outer$inner.class(含this$0字段),静态内部类同名但无this$0,局部及匿名类则为outer$1.class等编号形式。

Java 内部类编译后,全部生成独立的 .class 文件,文件名统一采用“外部类名 + $ + 标识符”的格式。这个 $ 不是 Java 源码中的语法符号,而是编译器为满足 JVM 类命名规范(禁止含 . 或 /)而做的扁平化处理。
成员内部类(非 static)
文件名格式为:外部类名$内部类名.class
- 例如:
public class Outer { class Inner { } }→ 编译后生成Outer$Inner.class - 若嵌套多层:
Outer中有Inner,Inner中又有Nested→ 生成Outer$Inner$Nested.class - 关键特征:字节码中包含一个隐式合成字段
this$0(类型为Outer),构造器会接收外部类实例作为参数
静态内部类(static)
文件名格式相同:外部类名$内部类名.class
- 例如:
public class Outer { static class StaticInner { } }→ 生成Outer$StaticInner.class - 区别不在文件名,而在字节码内容:无
this$0字段,不依赖外部类实例,可直接通过new Outer.StaticInner()创建
局部内部类(定义在方法内)
文件名格式为:外部类名$数字.class(从 $1 开始编号)
- 例如:
Outer的某个方法里定义了局部类class Local {}→ 生成Outer$1.class - 若同一方法中定义多个局部类,按出现顺序依次为
Outer$1.class、Outer$2.class… - 它会捕获所在方法的局部变量(这些变量必须是
final或事实 final),并在字节码中以合成字段保存
匿名内部类
文件名同样为:外部类名$数字.class
- 例如:
new Runnable() { public void run() {} }出现在Outer中 → 生成Outer$1.class - 同一外部类中每出现一个匿名类,编号递增:第一个是
$1,第二个是$2,依此类推 - 编译器还会根据它实现的接口或继承的父类,在字节码常量池中记录其二进制名称和父类信息
文件系统中不会出现 Outer.Inner.class 这样的名字——JVM 不允许类名含点号,所以 $ 是编译期强制引入的合法分隔符。反射、类加载、反编译或排查 NoClassDefFoundError 时,都得按这个命名规则去定位和识别。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











