public class Test {
interface Print{
void printNumber();
}
public static void work(Print print){
System.out.println("开始工作,现在打印一个数字");
print.printNumber();
System.out.println("结束工作。");
}
public static void main(String[] args){
int id = 5678;
work(new Print() {
@Override
public void printNumber() {
//id = 4444;
//假如我试图在这里更改id的值,就会报错,why?
System.out.println(id);
//没有报错是输出为5678
}
});
}
}
我把java学习中遇到的问题归结为以上测试类,如我上面的注释,当我重写接口中的方法时,在重写方法中无法修改id的值,这是为什么呢?
你實作這個介面時其實創建了一個內部類,這個內部類別是屬於外部類別的,而不是構造他的方法的,所以他沒法訪問構造他方法裡的非終態變數。
簡單的來說,你再people() 方法裡建立實現Print 接口的內部類,其中使用了id 這個變量,而其實你是在work() 方法裡才調用了Print ,其實這時候已經超出了people () 的訪問範圍,你是沒辦法訪問id 這個變數的。不過Java提供裡一個機制,你可以把id 參數傳入Print 中,實際上這些參數會複製到Print 中,不過為了確保產生歧義,這些參數都是終態的,你沒法修改它(避免你以為修改它就能修改people() 裡的id)。
我搞錯了。忽略我。 。
局部內部類別存取局部變量,局部變數應該被設定為final類型。
匿名內部類別存取外部成類員變數時,成員變數前應該加上final關鍵字
若試圖定義一個匿名內部類,並想使用在匿名內部類外部定義的一個對象,則編譯器要求外部對象為final
屬性。 --來自 thinking in java 185頁。
理解為:方法內部的匿名內部類別 存取本方法的參數清單及方法內局部變數時,變數應為final。
補充一點,想修改id,可將id宣告為 外部類別 靜態成員變數即可。
public class innerClass {
}
內部類別 詳見 程式設計思想 185頁前後。
//: Parcel8.java
// An anonymous inner class that performs
// initialization. A briefer version
// of Parcel5.java.
package c07.innerscopes;
若試圖定義一個匿名內部類,並想使用在匿名內部類外部定義的一個對象,則編譯器要求外部對象為final
屬性。這正是我們將dest()的自變數設為final 的原因。如果忘記這樣做,就會得到一條編譯期出錯提示。
只要自己只是想分配一個字段,上述方法就肯定可行。但如果需要採取一些類似建構器的行動,又該怎樣
操作呢?透過Java 1.1 的實例初始化,我們可以有效地為一個匿名內部類別建立一個建構器: