java中final的作用
1.修飾基礎數據成員的final: 這是final的主要用途,其含義相當於C/C++的const,即該成員被修飾為常量,意味著不可修改。如java.lang.Math類中的PI和E是final成員,其值為3.141592653589793和2.718281828459045。
2.修飾類或對象的引用的final: 在Java中,我們無法讓對象被修飾為final,而只能修飾對象的引用,這意味著即使你寫public final A a = new A(); 事實上a指向的對象的數據依然可以被修改,不能修改的是a本身的引用值,即你不能再對a進行重賦值。同樣的情況出現在數組中,比如public final int[] a = {1, 2, 3, 4, 5}
3.修飾方法的final: 修飾方法的final和C/C++中修飾成員對象的const大不相同。首先,修飾方法的final含義不是“不可修改”,而是指該方法不可被繼承成員重新定義。(註意,這裏所說的不能被重新定義,並不是指子類一定不能定義同名方法,如果父類的方法是私有類型,子類是允許定義該方法的,這裏指的不能重新定義是指不能通過改寫方法來使得方法重寫的多態性得以實現,如不希望A a = new B(); a.f();這樣的重寫方法情況出現)
示例:
public class A {
// final方法f
public final void f() {
System.out.println("類A中的final方法f被調用了");
}
}
public class B extends A {
// 編譯錯誤!父類的f方法是final類型,不可重寫!
//! public void f() {
//! System.out.println("類B中的方法f被調用了");
//! }
}
此外,當一個方法被修飾為final方法時,意味著編譯器可能將該方法用內聯(inline)方式載入,所謂內聯方式,是指編譯器不用像平常調用函數那樣的方式來調用方法,而是直接將方法內的代碼通過一定的修改後copy到原代碼中。這樣可以讓代碼執行的更快(因為省略了調用函數的開銷),比如在int[] arr = new int[3]調用arr.length()等。另一方面,私有方法也被編譯器隱式修飾為final,這意味著private final void f()和private void f()並無區別。
java中的內聯調用: 方法內聯是把目標方法的代碼"復制"到發起調用的方法中, 避免發生真是的方法調用, 編譯器在進行內聯時, 如果是非虛方法, 那麽直接進行內聯, 如果遇到虛方法(使用invokevirtual進行調用), 則java通過引入"類型繼承關系分析"(Class Hierarchy Analysis, CHA), CHA查詢此方法在當前程序下是否有多個目標版本可供選擇, 如果查詢結果只有一個版本, 則可以進行內聯, 稱為守護內聯, 如果CHA查詢得到多個版本的目標方法, 則編譯器會使用內聯緩存來完成方法內聯: 在未發生方法調用之前, 內聯緩存狀態為空, 當第一次調用發生後, 緩存記錄下方法接收者的版本信息, 並且每次進行方法調用的時候都比較接收者版本, 如果以後進來的每次調用的方法接收者版本都一樣則繼續使用內聯, 如果發生變化, 則說明程序使用了虛方法的多態特性, 則會取消內聯, 查找虛方法進行方法的分派.
4.修飾類的final: 當一個類被修飾為final時,它的含義很明確,就是不允許該類被繼承,也就是說,該類“絕後”了,任何繼承它的操作都會以編譯錯誤告終。這也凸顯出Java用final而不用const作為標識符的理由。
java中final的作用