源码
public class InnerClassTest {
final StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
public static void main(String[] args) throws Exception {
StringBuilder sb = new StringBuilder("124");
Callback callback = new Callback() {
@Override
public void process() {
System.out.println(sb);
sb.append("15790");
//sb=new StringBuilder();//Error:(28, 17) java: 从内部类引用的本地变量必须是最终变量或实际上的最终变量
}
};
test(callback);
System.out.println(sb);
}
public static void test(Callback callback) {
callback.process();
}
}
interface Callback{
void process();
}
编译
javac InnerClassTest.java
经过上述编译会生成三个class文件,分别为InnerClassTest.class、Callback.class、InnerClassTest$1.class;
比较特殊的是文件InnerClassTest$1.class,该文件为InnerClassTest的内部类Callback的实现。
在Callback的实现中使用到了外部类属性sb,那么sb在Callback实现中是如何使用的呢?
分析
通过javap -v -p InnerClassTest$1.class
反编译该class文件
······
Constant pool:
#1 = Fieldref #7.#23 // com/kanche/vehicle/service/impl/ASE$1.val$sb:Ljava/lang/StringBuilder;
······
#7 = Class #32 // com/kanche/vehicle/service/impl/ASE$1
······
#10 = Utf8 val$sb
#11 = Utf8 Ljava/lang/StringBuilder;
······
#23 = NameAndType #10:#11 // val$sb:Ljava/lang/StringBuilder;
······
#32 = Utf8 com/kanche/vehicle/service/impl/ASE$1
······
{
final java.lang.StringBuilder val$sb;
descriptor: Ljava/lang/StringBuilder;
flags: ACC_FINAL, ACC_SYNTHETIC
······
InnerClasses:
static #7; //class com/xxxx/vehicle/service/impl/InnerClassTest$1
通过上述反编译结果我们发现,该类的常量池中存在属性val$sb,而该属性被标注了ACC_FINAL flag,表明是一个不能修改的final对象。