Java 之 final 關鍵字

在 Java 中,有三種情況可能使用到 final:數據、方法和類。

1. final 數據

對於基本類型,final 使數值恆定不變;對於對象引用,final 使其引用不變,但是引用指向的對象本身可以被修改,數組也是對象。

public class finalData {
    private static final int VAL_1 = 1;
    private final Value value_1 = new Value(2);
    private final int a[] = {1, 2, 3, 4};

    public static void main(String[] args) {
        finalData finalData = new finalData();
       // finalData.VAL_1 = 2;  // error:Cannot assign a value to final variable 'VAL_1'
       // finalData.value_1 = new Value(3);  // error:Cannot assign a value to final variable 'value_1'
        finalData.value_1.i++;
       // finalData.a = new int[3];  //error:Cannot assign a value to final variable 'a'
        for (int i = 0; i < finalData.a.length; i++) {
            finalData.a[i]++;
        }
    }
}
class Value {
    int i;
    public Value(int i) {
        this.i = i;
    }
}

可以看到,雖然引用 value_1 不能改變,但是其成員 i 是可以改變的,數組 a 同理。

空白 final

空白 final 是指被聲明爲 final 但又未給定初值的域。但是無論什麼情況,編譯器都會確保空白 final 在使用前被初始化,否則會提示未初始化變量。

final 參數

將參數指明爲 final 時,意味着無法在方法中更改參數引用所指向的對象。

public class FinalArguments {
    void without(Gizmo g){
        g = new Gizmo();
        g.spin();
    }

    void with(final Gizmo g){
//        g = new Gizmo();   // Error,g 被定義爲 final
    }

    void g(final int i){
//        i++;     // Error,i 被定義爲 final
    }
    int f(final int i){
        return i+1;
    }

    public static void main(String[] args) {
        FinalArguments fa = new FinalArguments();
        Gizmo gizmo = new Gizmo();
        fa.with(gizmo);
        fa.without(gizmo);
    }

}
class Gizmo{
    public void spin(){}
}

2. final 方法

使用 final 方法可以把方法鎖定,防止任何繼承類修改它的定義。
類中所有的 private 方法都隱式地指定爲 final 的,繼承類無法取到 private 方法,當然也無法覆蓋它,所以爲 private 方法添加 final 修飾詞毫無意義。

class WithFinals {
    private final void f(){
        System.out.println("WithFinals.f()");
    }
    private void g(){
        System.out.println("WithFinals.g()");
    }
}
class OverridingPrivate extends WithFinals{
    // 雖然此時 OverridingPrivate 繼承了 WithFinals 類,但是這並不是重寫的父類方法,只是名字相同而已
    private final void f(){
        System.out.println("OverridingPrivate.f()");
    }
    private void g(){
        System.out.println("OverridingPrivate.g()");
    }

    public static void main(String[] args) {
        OverridingPrivate op = new OverridingPrivate();
        op.f();
        op.g();
        WithFinals wf = op;
//        wf.f();  子類對象無法調用父類對象的私有方法
//        wf.g();   子類對象無法調用父類對象的私有方法
    }
}

3. final 類

當使用 final 修飾類時,表明該類無法被繼承。
由於 final 類禁止繼承,所以 final 類中所有方法隱式指定爲 final 的,因爲無法覆蓋它們。

final class Dinosaur {
    int i = 1;
}
// class Further extends Dinosaur{}  // Error:Cannot inherit from final 'Dinosaur'

總結

被 final 修飾的數據/方法/類無法被改變

  1. final 修飾基本類型時,該數據被初始化一次後無法改變,當 final 修飾引用類型時,該引用不可變,但是引用指向的對象本身可變。
  2. final 修飾方法時,該方法無法被重寫
  3. final 修飾類時,該類無法被繼承
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章