Java方法局部内部类的Synthetic Fields如何关联方法局部变量的值
Java局部内部类变量访问机制与synthetic元素解答
局部内部类访问方法局部变量的实现原理
你的理解基本正确,只有命名细节上的差异,具体流程如下:
我们用一段示例代码来拆解:
public class OuterDemo { public Runnable getTask() { int count = 100; // 这里是effectively final变量 // 方法局部内部类 return new Runnable() { @Override public void run() { System.out.println(count); } }; } }
Javac编译后会生成两个字节码文件:OuterDemo.class和OuterDemo$1.class(后者就是局部内部类的字节码),内部实现逻辑是:
- 编译器会在局部内部类中生成一个私有、final的合成字段,命名规则为
val$[原局部变量名],示例中就是val$count,和原变量不会出现命名冲突 - 编译器会自动给局部内部类新增一个带对应参数的构造方法,创建内部类实例时,会把方法局部变量
count的当前值作为参数传入构造方法,给合成字段val$count赋值 - 内部类代码中所有对原变量
count的访问,都会被编译器替换成对自身合成字段val$count的访问
这也就是为什么要求变量必须是final或者effectively final:内部类拿到的只是变量的副本,要是原方法中的变量后续发生修改,副本无法同步更新,会出现逻辑不一致,Java直接从语法层面限制变量不可修改,从根源上规避了这个问题。
通用synthetic元素的定义
简单来说,synthetic(合成)元素是仅存在于编译后的字节码文件中,源代码里没有任何显式定义,由编译器自动生成,用来支撑Java各种语法特性实现的特殊元素,可以是字段、方法、构造器甚至类。
除了你提到的局部内部类的变量存储字段外,常见的合成元素还有这些:
- 非静态内部类中自动生成的
this$0字段,用来存储外部类的实例引用,实现内部类访问外部类成员的能力 - 当内部类需要访问外部类的私有成员时,编译器会给外部类生成
access$xxx格式的合成桥接方法,绕开私有成员的访问权限限制 - 泛型类型擦除后,为了保持多态特性自动生成的桥接方法
- 枚举类中自动生成的
values()、valueOf()方法也属于合成方法
内容的提问来源于stack exchange,提问作者francesco
相关产品推荐
相关产品推荐

