提起
final
變量,大家都是耳熟能詳,
- final成員變量表示常量,只能被賦值一次,賦值后值不再改變。
- final類不能被繼承,沒有子類,final類中的方法默認是final的。
- final方法不能被子類的方法覆蓋,但可以被繼承。
- final不能用于修飾構造方法
- final 常與 static一起用,作為常量來使用.
提問: 那么在一些方法的參數中定義為final是干嘛的?
答: 不希望這個變量在方法里面被修改,防止無意的修改而影響到調用方法外的變量
不知道這個答案是從哪個語言帶過來的, 感覺把final當成const了.
假設出現以下方法定義:
void fuc(final String string);
void fuc1(String string);
對于這種寫法,String本身就是一個不可以變的對象,并且其是作為基本參數類型,傳參進入后,方法里面改變了String的值外面也不會改變,因此這兩種寫法實際結果是一樣.只不過加了final,在string被賦值時IDE會直接報紅.
void fuc(final A a);
void fuc(A a);
對于這種寫法, A是一個對象,這樣寫不是代表A里面內容不能被改變,而是a不能被賦值為新對象了.
為什么使用匿名內部類的時候參數一定要加上final
讓我們寫一個類看一下
public class Test {
class Person {
String name;
int age;
}
private void func(final Person a) {
new Thread() {
@Override
public void run() {
super.run();
a.name = "hello";
}
}.start();
}
}
javac一下該文件,生成了3個class文件,我們看其中的兩個
內部類Person的class
class Test$Person {
String name;
int age;
Test$Person(Test var1) {
this.this$0 = var1;
}
}
匿名內部類Thread的class
class Test$1 extends Thread {
Test$1(Test var1, Person var2) {
this.this$0 = var1;
this.val$a = var2;
}
public void run() {
super.run();
this.val$a.name = "hello";
}
}
從這個匿名內部類的class文件我們可以看出兩點
- 其構造參數中增加了一個調用類.即我們所說的持有外部類的引用.
- 我們定義的final參數被當做構造方法傳了進來.至于為什么要把這個參數當做構造函數參數傳進來,因為調用它的方法參數是存在棧里面的,其生命周期隨著這個方法的調用結束而結束.而我們的異步任務可不是,有可能會執行很長時間.
那么final的關鍵字作用就凸顯了,Person參數要拷貝到內部類中,而拷貝會帶來不一致性, func
中是一個異步的操作,負責改變a的name的值. 假設Person a 不是final的.那么a可以被任意指向新的對象,那么傳給這個異步任務的對象還是老對象,這就造成了不一致.因此Java需要強制約束對象的一致性.因此必須是final的.
本文作者:Anderson/Jerey_Jobs
博客地址 : http://jerey.cn/
簡書地址 : Anderson大碼渣
github地址 : https://github.com/Jerey-Jobs