1. 程式人生 > >Java中final修飾符對不同變數的不同影響

Java中final修飾符對不同變數的不同影響

final修飾符可以用來修飾類、方法和變數,用於表示它修飾的類、方法和變數不可改變。final修飾變數時,表示該變數一旦獲得了初始值就不可被改變。

由於final變數獲取初始值之後就不能重新賦值,所以final修飾成員變數和區域性變數時有一定程度的不同。

final成員變數

成員變數是隨類初始化或者物件初始化而初始化的。在初始化時,系統會為類變數或者例項變數分配記憶體並分配預設值。

對於final修飾的成員變數而言,一旦有了初始值,就不能再被重新賦值。因此,如果沒有在定義成員變數時指定初始值,也沒有在初始化塊、構造器中為成員變數指定初值,那麼這些成員變數將一直是系統預設分配的0、’\u0000’、false或者null。這是沒有意義的,所以Java語法規定:final修飾的成員變數必須由程式設計師顯示地指定初始值。

final區域性變數

系統不會為區域性變數進行初始化,區域性變數必須由程式設計師顯示初始化。因此,使用final修飾區域性變數時,既可以在定義時指定預設值,也可以不指定預設值。

注意這段程式碼是有語法錯誤的:

public class Main {
	public void test(final int a){
		a = 5;//語法錯誤
	}
    public static void main(String[] args){
    	final int a = 4;
    	Main main = new Main();
    	main.test(a);
    }
}

因為形參在傳入方式時,會根據系統傳入的引數來完成初始化,因此使用final修飾的形參不能被賦值。

final 修飾的基本型別變數和引用型別變數的區別

當使用final修飾基本型別變數時,不能對基本型別變數重新賦值,因此基本型別變數不能被改變。但是對於引用型別變數而言,他儲存的僅僅是一個引用,final只保證這個引用型別變數所引用的地址不會改變,即一直引用一個物件,但這個物件可以被改變。

考慮下面這個示例:

public class Main {
    public static void main(String[] args){
    	final int[] a ;
final int b; int[] c = {1,2,3,4}; int d = 10; a = c; b = d; c[2] = 10; System.out.println(a[2]); //output 10 d = 1; System.out.println(b); //output 10 } }

可以執行“巨集替換”的final變數

對於一個final變數來說,只要滿足三個條件,這個final變數就不再是一個變數,而是相當於一個直接量。

  1. 使用final修飾符修飾
  2. 在定義該final變數時指定了初始值
  3. 該初始值可以在編譯時就被確認下來。

考慮下面的程式碼演示:

public class Main {
    public static void main(String[] args){
    	final String a="Amos ",b="H";
    	final String c = a+b;
    	final String d = "Amos H";
    	String e="Amos ",f="H";
    	final String g=e+f;
    	System.out.println(c==d);
    	//output true
    	System.out.println(c==g);
    	//output false
    }
}

因為變數c和變數d的值在編譯的時候就已經確定了,所以它們同時指向常量池中的Amos H 。因此輸出true。而對於變數g來說,它在定義的時候系統無法確認它的值,所以自然不能指向常量池。因此自然輸出false。

如果希望g也指向常量值,只要將e,f也定義為final變數即可。