Java,小而有料的final

原文鏈接: https://zhuanlan.zhihu.com/p/61092019

final這塊肉雖然小,但不可不知,因爲不僅面試可能會問,實際中也常使用。

就問你常量聲明時你爲什麼要加final?它有哪些作用?你思考過嗎?

final通常指被修飾的東西不能被改變的,不能被改變的原因旺往往出於設計和效率的考慮。

先看final能修飾什麼?

  • 修飾變量
  • 修飾方法
  • 修飾類
  • 修飾參數

不同的修飾有什麼不同的作用呢?下面慢慢道來:

final常量

final修飾的常量必須在被使用前進行初始化,初始化的方式無非兩種:定義時賦值或構造函數內賦值

final修飾常量基本類型和引用類型有些不同,我分開講。

基本數據類型

public class Test {
    private final int A;
    private final int B = 3;
    private final int C = new Random().nextInt();

    public Test() {
        this.A = 5;
    }

    public Test(int a) {
        this.A = a;
    }
}

爲什麼常量B要用final修飾?

因爲這種確定值(定義便立即賦值)的final常量,編譯器會在編譯時將該常量值帶入到任何可能用到它的計算式中,這會減輕運行時的一些負擔。
比如 int d = 3 * B; 那麼編譯後相當於 int d = 9;

final修飾的常量值是在編譯期間被確定的嗎?

注意上面的變量C,我們並不能以爲final修飾的就能在編譯時知道它的值,C的值只有在運行時被初始化時纔會顯現。

引用類型

引用類型不能改變指的是引用被初始化指向一個對象後,就再也無法改爲指向其他對象,但其指向的對象本身是可以被修改的。

public class B {
    //final常量d指向了對象D
    private final D d = new D();

    //這個方法改變了對象D的內容
    public D change() {
        this.d.setS("change");
        return d;
    }

    //注意這個方法,將常量d的引用改變了
    public D refnewD() {
        this.d = new D();
        return d;
    }

    class D {
        private String s = "init";

        public String getS() {
            return s;
        }

        public void setS(String s) {
            this.s = s;
        }
    }
}

上面代碼是無法編譯的,因爲this.d=new D()會提示Cannot assign a value to final variable ‘d’,但是你卻可以調用change()方法來改變d對象的s變量值。

final方法

爲什麼使用final修飾方法

  1. 設計:把方法鎖定,防止繼承類修改它的含義。

  2. 效率:早期編譯器會將final方法所有的調用轉爲內嵌調用,隨着JVM的提高,這種方式已被丟棄。

final和private

當一個方法被private修飾,這會隱式的指定爲final,這也會使得子類無法覆蓋此方法,可以對private方法增加final修飾,但對該方法並不能增加任何意義。

final類

String類是final應用的典型例子,可去查看面試別再問我String了。

爲什麼要把類指定爲final?

出於安全考慮或其他原因,你不希望該類有任何變動或被繼承。

一旦類被final修飾,即代表final類中的所有成員變量和方法都會隱式的final。

final參數

在方法的參數列表中將參數指定爲final,即代表該參數引用所指向的對象是無法改變的;

若爲基本類型,則表示值可以讀取,但無法修改。修飾情況和final常量類似。也可結合這題不會!別說你懂值傳遞與引用傳遞。

final相關

staticfinal

  1. static強調的是該數據只存在一份,且是屬於類的,不是屬於對象。

  2. final強調該數據不可變,且是屬於對象的。

public class C {
    private final double A = 3.14D;
    private static double b = 3.14D;

    public static void main(String[] args) {
        new C();
        new C();
        new C();
    }
}

上面代碼運行後,A會存在3個,但b只有一個。

final,finally和finalize

  • finally
    是在異常處理時配合try-catch執行清理操作,需要清理的資源包括:打開的文件或網絡連接等,它會把內存之外的資源恢復到他們的初始狀態。無論try中是否有異常出現,finally裏的操作都會被執行。
  • finalize
    這是Object基類的一個方法,垃圾收集器在將對象清除出內存之前調用的清理資源方法,且此方法只會被系統調用一次,其實finalize能做的工作,try-finally能做的更好,《深入理解Java虛擬機》中建議大家忘掉這個方法的存在。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章