匿名內部類引用外面的局部變量要把局部變量改爲final類型的原因

Why inner classes require “final” outer instance variables ?

    

finalJTextFieldjtfContent =newJTextField();
    btnOK.addActionListener(newjava.awt.event.ActionListener(){
        publicvoidactionPerformed(java.awt.event.ActionEventevent){
            jtfContent.setText("I am OK");
        }
    });

If I omit final, I see the error "Cannot refer to a non-final variable jtfContent inside an inner class defined in a different method".

Why must an anonymous innter class require the outer classes instance variable to be final in order to access it?

 

 

 

Answer:

 

The methods in an anonymous class don't really have access to local variables and method parameters. Rather, when an object of the anonymous class is instantiated, copies of the final local variables and method parameters referred to by the object's methods are stored as instance variables in the object. The methods in the object of the anonymous class really access those hidden instance variables. [1]

Thus, the local variables and method parameters accessed by the methods of the local class must be declared final to prevent their values from changing after the object is instantiated.

 

 

 

 

局部匿名類在源代碼編譯後也是要生成對應的class文件的(一般會是A$1.class這種形式的文件),那麼這個二進制文件是獨立於其外圍類(A.class)的,就是說它無法知道A類中方法的變量。但是A$1.class又確實要訪問A類對應方法的局部變量的值。。。怎麼辦呢?於是乾脆就要求“匿名內部類調用的方法內局部變量必須爲final”,這樣A$1.class訪問A類方法局部變量部分就直接用常量來表示

這是一個編譯器設計的問題,如果你瞭解java的編譯原理的話很容易理解。
首先,內部類被編譯的時候會生成一個單獨的內部類的.class文件,這個文件並不與外部類在同一class文件中。
當外部類傳的參數被內部類調用時,從java程序的角度來看是直接的調用例如:
public void dosome(final String a,final int b){
class Dosome{public void dosome(){System.out.println(a+b)}};
Dosome some=new Dosome();
some.dosome();
}
從代碼來看好像是那個內部類直接調用的a參數和b參數,但是實際上不是,在java編譯器編譯以後實際的操作代碼是
class Outer$Dosome{
public Dosome(final String a,final int b){
this.Dosome$a=a;
this.Dosome$b=b;
}
public void dosome(){
System.out.println(this.Dosome$a+this.Dosome$b);
}
}}
從以上代碼看來,內部類並不是直接調用方法傳進來的參數,而是內部類將傳進來的參數通過自己的構造器備份到了自己的內部,自己內部的方法調用的實際是自己的屬性而不是外部類方法的參數。

這樣理解就很容易得出爲什麼要用final了,因爲兩者從外表看起來是同一個東西,實際上卻不是這樣,如果內部類改掉了這些參數的值也不可能影響到原參數,然而這樣卻失去了參數的一致性,因爲從編程人員的角度來看他們是同一個東西,如果編程人員在程序設計的時候在內部類中改掉參數的值,但是外部調用的時候又發現值其實沒有被改掉,這就讓人非常的難以理解和接受,爲了避免這種尷尬的問題存在,所以編譯器設計人員把內部類能夠使用的參數設定爲必須是final來規避這種莫名其妙錯誤的存在。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章