Java併發--final關鍵字

xiang發表於2020-08-18

一、final使用場景

final可以稀釋變數,方法和類,用於便是修飾的內容一旦賦值之後不會再被改變,比如string類就是一個final型別的類。

二、final修飾變數

在Java中變數可以分為成員變數和區域性變數

成員變數

通常每個類中成員變數可以分為類變數(static修飾的變數)以及例項變數針對這兩種型別的變數賦初始值的時機是不同的。

類變數可以再宣告變數的時候直接賦初始值或者在靜態程式碼塊中給類變數賦初始值;而例項變數可以在宣告變數的時候給例項變數賦初始值,在非靜態初始化塊中以及構造器中賦初始值。

類變數有兩個時機賦初始值,而例項變數可以有三個時機賦初始值。當final變數未初始化時系統不會進行隱式初始化,會出現報錯。

 

將這幾種情況歸納整理一下:

類變數:必須要在靜態初始化塊中指定初始值或者宣告該類變數時指定初始值,而且只能在這兩個地方之一警醒指定;

例項變數:必須要在非靜態初始化塊,宣告該例項變數或者在構造器中指定初始值,而且只能在這三個地方警醒指定。

區域性變數

final區域性變數有程式設計師進行顯示初始化,如果final區域性變數已經進行了初始化則後面就不能再次進行更改,如果final變數未進行初始化,可以進行賦值,當且僅有一次賦值,一旦賦值之後再次賦值就會出錯。

基本資料型別和引用資料型別

final修飾的基本資料型別和引用型別有區別嗎?

通過上面的例子我們已經看出來,如果final修飾的是一個基本資料型別的資料,一旦賦值後就不能再次更改,那麼,如果final修飾的是引用資料型別?這個引用的物件能夠改變嗎?

package passtra;

public class FinalExample{
    
    //在宣告final例項成員變數時進行賦值
    private final static Person person=new Person(25, 175);
    
    public static void main(String[] args) {
        //對final引用資料型別person進行更改
        person.age=22;
        System.err.println(person.toString());
    }
    
    
    static class Person{
        private int age;
        private int height;
        public Person(int age, int height) {
            super();
            this.age = age;
            this.height = height;
        }
        @Override
        public String toString() {
            return "Person [age=" + age + ", height=" + height + "]";
        }
        
    }
}

當我們對final修飾的應用資料型別變數person的屬性改成22,是可以操作成功的。

通過程式碼可以看出,當final修飾基本資料型別時,不能對基本資料型別變數重新賦值,因此基本資料型別不能被改變,而對於引用資料型別,它僅僅儲存的是一個引用,final只保證引用型別所引用的地址不會發生改變,即一直引用這個物件,但這個物件屬性是可以改變的。

巨集變數

利用final變數的不可更改性,在馬祖下面三個條件時,該變數就會成為一個巨集變數,即一個常量。

使用final修飾符修飾,在定義該final變數時就指定了初始值,該初始值在編譯時就能夠唯一指定。

注意:

當程式中其他地方使用該巨集變數時,編譯器會直接替換該變數的值。

三、final修飾方法

重寫

當父類的方法被final修飾的時候,子類不能重寫父類的該方法。你如在object中getClass()方法就是說final修飾的,我們就不能重寫該方法,但是hasdhCode()不是被final修飾的,我們就可以重寫hashCode()方法

過載

package passtra;

public class FinalExample{
    
    public final void test(){
        
    }
    //沒有報錯
    public final void test(int i){
        
    }
    
}

可以看出被final修飾的方法可以過載

四、final修飾類

當一個類被final修飾時,表明該類不能被子類繼承

子類往往可以重寫父類的方法和屬性,會帶來一定的安全隱患,因此當一個類不希望被繼承是就可以用final修飾。

五、final在JDK中有哪些應用

final經常被用作不變類上,利用final的不可更改性。

不變類

不變類的意思是建立該類的例項後,該例項的例項變數時不可改變的。滿足以下條件可以成為不變類:

  • 使用private和final修飾該類的成員變數;
  • 提供帶引數的構造器用於初始化類的成員變數;
  • 僅為該類的成員變數提供getter方法,不提供setter方法,因為普通方法無法修改final修飾的成員變數;
  • 如果有必要就重寫object的hashCode和equals方法應該保證用equals判斷相同的兩個物件其HashCode值也是相等的。

 JDK中提供的八個包裝類和String類都是不可變的,可以看看string的實現

private final char value[];

可以看出string的value就是final修飾的,上述其他幾條性質也是吻合的。

相關文章