CodeGym /Java Blog /Toto sisi /讓我們談談 Java 中的 final 關鍵字
John Squirrels
等級 41
San Francisco

讓我們談談 Java 中的 final 關鍵字

在 Toto sisi 群組發布
Java 有這個關鍵字——final。它可以應用於類、方法、變量(包括方法參數)。對於一個類,final關鍵字表示該類不能有子類,即禁止繼承……這在創建不可變(unchangeable)對象時很有用。例如,String 類被聲明為 final。

    public final class String {
    }
    
    class SubString extends String { // Compilation error
    }
我還應該注意,final 修飾符不能應用於抽像類(具有關鍵字 abstract 的類),因為它們是相互排斥的概念。對於 final 方法,修飾符意味著該方法不能在子類中被重寫。當我們想要防止更改原始實現時,這很有用。

    public class SuperClass {
        public final void printReport() {
            System.out.println("Report");
        }
    }

    class SubClass extends SuperClass { 
        public void printReport() { //Compilation error
            System.out.println("MyReport");
        }
    }
對於基本類型的變量,final 關鍵字意味著值一旦賦值就不能更改。對於引用變量,就是指一個對像被賦值後,就不能再改變對該對象的引用。這個很重要!不能更改引用,但可以更改對象的狀態。Java 8 引入了一個新概念:effectively final。它僅適用於變量(包括方法參數)。最重要的是,儘管明顯沒有 final 關鍵字,但變量的值在初始化後不會改變。換句話說,可以將 final 關鍵字應用於這樣的變量而不會出現編譯錯誤。實際上,final 變量可以在本地類(本地內部類)、匿名類(匿名內部類)和流(Stream API)中使用。

        public void someMethod() {
            // In the example below, both a and b are effectively final, since they are assigned values only once:
            int a = 1;
            int b;
            if (a == 2) b = 3;
            else b = 4;
            // c is NOT effectively final since its value changes
            int c = 10;
            c++;
            
            Stream.of(1, 2).forEach(s-> System.out.println(s + a)); // OK
            Stream.of(1, 2).forEach(s-> System.out.println(s + c)); // Compilation error
        }
現在,讓我們進行一次小採訪。畢竟,完成 CodeGym 課程的目標是成為一名 Java 開發人員並找到一份有趣且收入豐厚的工作。那麼,讓我們開始吧。
  1. 對於聲明為 final 的數組,我們能說些什麼呢?

  2. 我們知道 String 類是不可變的:該類被聲明為 final。字符串值存儲在用關鍵字 final 標記的 char 數組中。


public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

我們可以替換 String 對象的值(而不更改對對象的引用)嗎?這些是真正的面試問題。而實踐表明,很多考生都答錯了。了解如何使用 final 關鍵字非常重要,尤其是對於引用變量。在您考慮這一點時,我將向 CodeGym 團隊提出一個小請求。請給文本編輯器添加一個塊的能力,當你點擊它時,它的內容可以顯示/隱藏。 答案:
  1. 數組是一個對象,所以 final 關鍵字意味著一旦分配了對數組的引用,就不能更改該引用。也就是說,您可以更改對象的狀態。

    
            final int[] array = {1, 2, 3, 4, 5};
            array[0] = 9;	 // OK, because we're changing the contents of the array: {9, 2, 3, 4, 5}
            array = new int[5]; // Compilation error
    
  2. 我們可以。最主要的是理解棘手的 final 關鍵字在與對像一起使用時的含義。反射 API 可用於替換值。


import java.lang.reflect.Field;

class B {
    public static void main(String[] args) throws Exception {
        String value = "Old value";
        System.out.println(value);

        // Get the String class's value field
        Field field = value.getClass().getDeclaredField("value");
        // Make it mutable
        field.setAccessible(true);
        // Set a new value
        field.set(value, "CodeGym".toCharArray());

        System.out.println(value);

        /* Output:
         * Old value
         * CodeGym
         */
    }
}
請注意,如果我們嘗試以這種方式更改原始類型的最終變量,那麼什麼也不會發生。我建議您說服自己:例如,創建一個帶有 final int 字段的 Java 類,並嘗試使用 Reflection API 更改它的值。祝你們好運!
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION