java基礎-final用法

1、final關鍵字的含義

    final在Java中能夠聲明成員變量、方法、類以及本地變量。一旦你將引用聲明final,你將「不能改變」這個引用了,編譯器會檢查代碼,若是你試圖將變量再次初始化的話,編譯器會報編譯錯誤。java

2、修飾數據

    在編寫程序時,咱們常常須要說明一個數據是不可變的,咱們成爲常量。在java中,用final關鍵字修飾的變量,只能進行一次賦值操做,而且在生存期內不能夠改變它的值。更重要的是,final會告訴編譯器,這個數據是不會修改的,那麼編譯器就可能會在編譯時期就對該數據進行替換甚至執行計算,這樣能夠對咱們的程序起到一點優化。不過在針對基本類型和引用類型時,final關鍵字的效果存在細微差異。咱們來看下面的例子:程序員

class Value {
    int v;
    public Value(int v) {
        this.v = v;
    }
}

public class finaltest {
    final int f1 = 1;
    final int f2;
    public finaltest() {
        f2 = 2;
    }
    public static void main(String[] args) {
        final int value1 = 1;
//        value1 = 4;
        System.out.println(value1);
        final double value2;
        value2 = 2.0;
        System.out.println(value2);
        final Value value3 = new Value(1);
        System.out.println(value3.v);
        value3.v = 4;
        System.out.println(value3.v);
    }
}

    上面的例子中,咱們先來看一下main方法中的幾個final修飾的數據,在給value1賦初始值以後,咱們沒法再對value1的值進行修改,final關鍵字起到了常量的做用。從value2咱們能夠看到,final修飾的變量能夠不在聲明時賦值,便可以先聲明,後賦值。value3時一個引用變量,這裏咱們能夠看到final修飾引用變量時,只是限定了引用變量的引用不可改變,即不能將value3再次引用另外一個Value對象,可是引用的對象的值是能夠改變的,從內存模型中咱們看的更加清晰:性能

    上圖中,final修飾的值用粗線條的邊框表示它的值是不可改變的,咱們知道引用變量的值其實是它所引用的對象的地址,也就是說該地址的值是不可改變的,從而說明了爲何引用變量不能夠改變引用對象。而實際引用的對象其實是不受final關鍵字的影響的,因此它的值是能夠改變的。優化

    另外一方面,咱們看到了用final修飾成員變量時的細微差異,由於final修飾的數據的值是不可改變的,因此咱們必須確保在使用前就已經對成員變量賦值了。所以對於final修飾的成員變量,咱們有且只有兩個地方能夠給它賦值,一個是聲明該成員時賦值,另外一個是在構造方法中賦值,在這兩個地方咱們必須給它們賦初始值。this

最後咱們須要注意的一點是,同時使用static和final修飾的成員在內存中只佔據一段不能改變的存儲空間spa

3、修飾方法參數

    前面咱們能夠看到,若是變量是咱們本身建立的,那麼使用final修飾表示咱們只會給它賦值一次且不會改變變量的值。那麼若是變量是做爲參數傳入的,咱們怎麼保證它的值不會改變呢?這就用到了final的用法,即在咱們編寫方法時,能夠在參數前面添加final關鍵字,它表示在整個方法中,咱們不會(其實是不能)改變參數的值:設計

public class finaltest {
    public void finalFunc(final int i, final Value value) {
        // i = 5; 不能改變i的值
        // v = new Value(); 不能改變v的值
        value.v = 5; // 能夠改變引用對象的值
    }
}

4、修飾方法

    第三種方式,即用final關鍵字修飾方法,它表示該方法不能被重寫。這種使用方式主要是從設計的角度考慮,即明確告訴其餘可能會繼承該類的程序員,不但願他們去重寫這個方法。這種方式咱們很容易理解,然而,關於private和final關鍵字還有一點聯繫,這就是類中全部的private方法都隱式地指定爲是final的,因爲沒法在類外使用private方法,因此也就沒法重寫它。code

5、修飾類

    瞭解了final關鍵字的其餘用法,咱們很容易能夠想到使用final關鍵字修飾類的做用,那就是用final修飾的類是沒法被繼承的。對象

6、總結

    final關鍵字是咱們常用的關鍵字之一,它的用法有不少,可是並非每一種用法都值得咱們去普遍使用。對於第四和第五用法,咱們卻甚少使用。這不是沒有道理的,從final的設計來說,這兩種用法甚至能夠說是雞肋,由於對於開發人員來說,若是咱們寫的類被繼承的越多,就說明咱們寫的類越有價值,越成功。即便是從設計的角度來說,也沒有必要將一個類設計爲不可繼承的。Java標準庫就是一個很好的反例,特別是Java 1.0/1.1中Vector類被如此普遍的運用,若是全部的方法均未被指定爲final的話,它可能會更加有用。如此有用的類,咱們很容易想到去繼承和重寫他們,然而,因爲final的做用,致使咱們對Vector類的擴展受到了一些阻礙,致使了Vector並無徹底發揮它應有的所有價值。繼承

它的主要用法有如下四種:

  • 修飾數據:包括成員變量和局部變量,該變量只能被賦值一次且它的值沒法被改變。對於成員變量來說,咱們必須在聲明時或者構造方法中對它賦值;
  • 修飾方法參數:表示在變量的生存期中它的值不能被改變;
  • 修飾方法:表示該方法沒法被重寫;
  • 修飾類:表示該類沒法被繼承。

7、相關final的重要知識點

  1. final關鍵字能夠用於成員變量、本地變量、方法以及類。
  2. final成員變量必須在聲明的時候初始化或者在構造器中初始化,不然就會報編譯錯誤。
  3. 你不可以對final變量再次賦值。
  4. 本地變量必須在聲明時賦值。
  5. 在匿名類中全部變量都必須是final變量。
  6. final方法不能被重寫。
  7. final類不能被繼承。
  8. final關鍵字不一樣於finally關鍵字,後者用於異常處理。
  9. final關鍵字容易與finalize()方法搞混,後者是在Object類中定義的方法,是在垃圾回收以前被JVM調用的方法。
  10. 接口中聲明的全部變量自己是final的。
  11. final和abstract這兩個關鍵字是反相關的,final類就不多是abstract的。
  12. final方法在編譯階段綁定,稱爲靜態綁定(static binding)。
  13. 沒有在聲明時初始化final變量的稱爲空白final變量(blank final variable),它們必須在構造器中初始化,或者調用this()初始化。不這麼作的話,編譯器會報錯「final變量(變量名)須要進行初始化」。
  14. 將類、方法、變量聲明爲final可以提升性能,這樣JVM就有機會進行估計,而後優化。
相關文章
相關標籤/搜索