再次深入final關鍵字- 匿名類用到的變量為什么一定要是final的呢?


提起final變量,大家都是耳熟能詳,

  1. final成員變量表示常量,只能被賦值一次,賦值后值不再改變。
  2. final類不能被繼承,沒有子類,final類中的方法默認是final的。
  3. final方法不能被子類的方法覆蓋,但可以被繼承。
  4. final不能用于修飾構造方法
  5. 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文件我們可以看出兩點

  1. 其構造參數中增加了一個調用類.即我們所說的持有外部類的引用.
  2. 我們定義的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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,765評論 18 399
  • 一:java概述:1,JDK:Java Development Kit,java的開發和運行環境,java的開發工...
    ZaneInTheSun閱讀 2,687評論 0 11
  • Advanced Language Features 知識點:一. static修飾符 static修飾符可以用來...
    風景涼閱讀 456評論 0 0
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,915評論 18 139
  • 你跟好朋友聊天我會偷偷看著你, 知道為什麼嗎? 因為我喜歡看你笑, 只有跟好朋友聊天你會笑得很開心, 而我們之間,...
    書寫心情閱讀 170評論 0 3