2010年10月11日星期一

Java 局部内部类对外部变量的引用

Java 的Local Inner class 访问方法的局部变量的时候,变量或者方法的参数需要被声明为Final,但是Java内部是如何实现的了?这里还是以看代码吧。源代码如下:





public class InnerLocalTest {


final String t = "jinjian";


System.out.println(name);


class LocalCounter implements Counter {


public LocalCounter() {


System.out.println("LocalCounter");


}


public LocalCounter(String name){




}


public int next() {


System.out.println(name);


System.out.println(t);


return count++;


}


}




用eclipse自带的编译器,很多反编译软件都不能正常的工作,可能是做了某些特别的优化或者处理,这里用的是sun自带的编译器,这里再看看反编译出来的代码:



// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.


// Jad home page: http://www.kpdus.com/jad.html


// Decompiler options: packimports(3)


// Source File Name: InnerLocalTestOrg.java


import java.io.PrintStream;


public class InnerLocalTestOrg


{


class LocalCounter


implements Counter


{ public int next()


{


return count++;


}


final InnerLocalTestOrg this$0;


LocalCounter()


{


this$0 = InnerLocalTestOrg.this;


super();


}


}


public InnerLocalTestOrg()


{


count = 0;


}


Counter getCounter(final String name)


{


System.out.println(name);


class _cls1LocalCounter


implements Counter


{


public int next()


{


System.out.println(name);


System.out.println("jinjian");


return count++;


}


final String val$name;


final InnerLocalTestOrg this$0;


public _cls1LocalCounter()


{


this$0 = InnerLocalTestOrg.this;


name = s;


super();


System.out.println("LocalCounter");


}



public _cls1LocalCounter(String s1)


{


this$0 = InnerLocalTestOrg.this;


name = s1;


super();


}


}


return new _cls1LocalCounter();


}


.............



这里我可以看到,申明为final的变量name是作为编译器重新生成的一个Inner class的构造函数传入的,这样才保证了getCounter执行完后,对name的应用依然可以使用,而不是直接使用作为参数传入的引用。对于本地的final变量,直接进行了替换。对外部类变量的引用,就像很多书上所说的那样,因为它保留了一个指向外部类的引用。