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 開發人員並找到一份有趣且收入豐厚的工作。那麼,讓我們開始吧。
-
對於聲明為 final 的數組,我們能說些什麼呢?
-
我們知道 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 團隊提出一個小請求。請給文本編輯器添加一個塊的能力,當你點擊它時,它的內容可以顯示/隱藏。 答案:
-
數組是一個對象,所以 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
-
我們可以。最主要的是理解棘手的 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 更改它的值。祝你們好運!
GO TO FULL VERSION