是變量的作用域的問題窒舟,因為匿名內(nèi)部類是出現(xiàn)在一個方法的內(nèi)部的窗怒,如果它要訪問這個方法的參數(shù)或者方法中定義的變量,則這些參數(shù)和變量必須被修飾為final吏恭。
一個xx.java類里面有匿名內(nèi)部類拗小,編譯出來的class文件會有xx.class 、xx$1.calss...
例如:
public class InnerClass {
public static void test(final String s){
InnerClass c = new InnerClass(){
public void m(){
int x = s.hashCode();
System.out.println(x);
}
};
}
}
編譯出來的兩個class文件是:InnerClass.class和 InnerClass$1.class,代碼分別如下:
package smartpush;
import java.io.PrintStream;
public class InnerClass
{
public static void test(String s)
{
InnerClass c = new InnerClass(s) {
public void m() {
int x = this.val$s.hashCode();
System.out.println(x);
}
};
}
}
package smartpush;
import java.io.PrintStream;
class 1 extends InnerClass
{
public void m()
{
int x = this.val$s.hashCode();
System.out.println(x);
}
}
這說明雖然匿名內(nèi)部類在方法的內(nèi)部樱哼,但實際編譯的時候哀九,內(nèi)部類會編譯成一個inner_object,而外部類中的方法中的變量s只是方法的局部變量搅幅,s的作用域只在這個方法內(nèi)部有效阅束。查看反編譯出來的源碼,內(nèi)部類 class 1
int x = this.val$s.hashCode();
內(nèi)部類使用this.val$s引用了方法內(nèi)部的變量s
對于一個final變量:
如果是基本數(shù)據(jù)類型的變量茄唐,則其數(shù)值一旦在初始化之后便不能更改息裸;
如果是引用類型的變量,則在對其初始化之后便不能再讓其指向另一個對象沪编。
因此內(nèi)部類要引用變量s,編譯器就要保證s的引用 this.val$s在初始化后就不能再改變呼盆。
不然如果在內(nèi)部類的方法執(zhí)行前,s的引用指向了其他地方蚁廓,例如
s="321"
這樣匿名類的變量指向B而外部的變量卻指向A了访圃,這結(jié)果顯然是不能接受的
于是為了保證變量引用的一致性,內(nèi)部類只能訪問final變量相嵌。
http://stackoverflow.com/questions/3910324/why-java-inner-classes-require-final-outer-instance-variables
http://stackoverflow.com/questions/1299837/cannot-refer-to-a-non-final-variable-inside-an-inner-class-defined-in-a-differen
http://feiyeguohai.iteye.com/blog/1500108
http://blog.csdn.net/woshichunchun/article/details/7925823
http://blog.csdn.net/axman/article/details/1460544