Java中final幾種常用用法及final關鍵字的作用說明


Java中的final共有三種用法:

final成員變量
當你在類中定義變量時,在其前面加上final關鍵字,那便是說,這個變量一旦被初始化便不可改變,這里不可改變的意思對基本的類型來說是其值不可變,而對於對象變量來說其引用不可再變,但引用變量所指向的對象中的內容還是可以改變的

其初始化可以在三個地方:
一是其定義處,也就是說在final變量定義時直接給其賦值;
二是在構造方法中,而且在java1.1以前,只能時在定義的時候給賦值;
三是在初始化代碼塊中 {} 或者 static{}
下面這段代碼演示了這一點:
public class FinalUseTest {

final double PI = 3.14; // 在定義時便給址值
final int i; // 因為要在構造函數中進行初始化,所以此處便不可再給值
final List<FinalUseTest> list; // 此變量也與上面的一樣

FinalUseTest() {
i = 100;
list = new LinkedList<>();
}

FinalUseTest(int ii, List<FinalUseTest> l) {
i = ii;
list = l;
}

public static void main(String[] args) {

FinalUseTest b = new FinalUseTest();
b.list.add(new FinalUseTest());//引用不可變,但引用指向的內容是可以變的
// b.i=25;// syntax error i是不可變的
// b.list=new ArrayList();// 錯誤,對象引用是不可變的
System.out.println("I=" + b.i + " List Type:" + b.list.getClass());
b = new FinalUseTest(23, new ArrayList<FinalUseTest>());
b.list.add(new FinalUseTest());
System.out.println("I=" + b.i + " List Type:" + b.list.getClass());
}
}

再例如,對於如下語句:

final static StringBuffer a=new StringBuffer("dachun");
  執行如下語句將報告編譯期錯誤:
a=new StringBuffer("");
  但是,執行如下語句則可以通過編譯:
a.append("zuishuai");

有人在定義方法的參數時,可能想采用如下形式來阻止方法內部修改傳進來的參數對象:
public void method(final StringBuffer param){
}
實際上,這是辦不到的,在該方法內部仍然可以增加如下代碼來修改參數對象,其它對象亦如此:
param.append("a");

此程序很簡單的演示了final的常規用法。在這里使用在構造函數中進行初始化的方法,這使你有了一點靈活性。如FinalUseTest的兩個重載構造函數所示,第一個缺省構造函數會為你提供默認的值,重載的那個構造函數會根據你所提供的值或類型為final變量初始化。然而有時你並不需要這種靈活性,你只需要在定義時便給定其值並永不變化,這時就不要再用這種方法。在main方法中有兩行語句注釋掉了,如果你去掉注釋,程序便無法通過編譯,這便是說,不論是i的值或是list的類型,一旦初始化,確實無法再更改。然而b可以通過重新初始化來指定i的值或 list的類型,輸出結果中顯示了這一點:
I=100 List Type:class java.util.LinkedList
I=23 List Type:class java.util.ArrayList

還有一種用法是定義方法中的參數為final,對於基本類型的變量,這樣做並沒有什么實際意義,因為基本類型的變量在調用方法時是傳值的,也就是說你可以在方法中更改這個參數變量而不會影響到調用語句,然而對於對象變量,卻顯得很實用,因為對象變量在傳遞時是傳遞其引用,這樣你在方法中對對象變量的修改也會影響到調用語句中的對象變量,當你在方法中不需要改變作為參數的對象變量時,明確使用final進行聲明,會防止你無意的修改而影響到調用方法。


final方法
將方法聲明為final,那就說明你已經知道這個方法提供的功能已經滿足你要求,不需要進行擴展,並且也不允許任何從此類繼承的類來覆寫這個方法,但是繼承仍然可以繼承這個方法,也就是說可以直接使用。

另外有一種被稱為inline的機制,它會使你在調用final方法時,直接將方法主體插入到調用處,而不是進行例行的方法調用,例如保存斷點,壓棧等,這樣可能會使你的程序效率有所提高,然而當你的方法主體非常龐大時,或你在多處調用此方法,那么你的調用主體代碼便會迅速膨脹,可能反而會影響效率,所以你要慎用final進行方法定義。

類中所有的private方法從某種意義上講都是屬於final的,因為他們在其它地方沒法覆蓋,你可以在一個private方法前加final修飾符,但沒什么意義。

final類
當你將final用於類身上時,你就需要自習考慮,因為一個final時無法被任何人繼承的,那也就意味着此類在一個繼承樹中是一個葉子類,並且此類的設計已被認為很完美而不需要進行修改或擴展。

對於final類中的成員變量,你可以定義其為final,也可以不是final;而對於方法,由於所屬類為final的關系,自然也就成了final型的。你也可以明確的給final類中的方法加上一個final,但顯然沒有意義。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM