源码

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对象。