Java之路:你真的了解final吗?
1、用final修飾數據
(1)用final修飾基本數據類型時,即聲明了一個常量,必須對其進行賦值。
(2)當對對象的引用使用final時,final使引用恒定不變。一旦引用被初始化指向一個對象,就無法把它改為指向另一個對象。然而對象其自身卻是可以被修改的。
class Value {int i;public Value(int i) { this.i = i; } } public FinalData {private Value v1 = new Value(11);private final Value v2 = new Value(22);private final int[] a = {1, 2, 3, 4, 5};public static void main(String[] args) {FinalData fd1 = new FinalData();fd1.v2.i++; // v2是對象,不是常量,v2用final修飾,無法把它改為指向另一對象,但對象自身是可以被修改的fd1.v1 = new Value(9); // v1不是final,可以將它指向另一個對象 // fd1.v2 = new Value(0); // v2是final,不可以將它指向另一個對象for (int i = 0; i < fd1.a.length; i++){fd1.a[i]++; // 數組是對象,對象不是常量,其自身可以改變} // fd1.a = new int[3]; //錯誤,數組a是final修飾的引用,無法將它指向另一個對象} }(3)一個既是static又是final的域只占據一段不能改變的存儲空間。
(4)Java允許生成“空白final”,所謂空白final是指被聲明為final但又未給定初值的域。無論什么情況,編譯器都確保空白final在使用前必須被初始化。總之,final是一定要初始化的,如果不在聲明處初始化,那就在構造器中初始化。記住一定要初始化,否則編譯不通過。
class Poppet {private int i;Poppet(int i) { this.i = i; } } public class BlankFinal {private final int i = 0;private final int j; // 空白finalprivate final Poppet p; // 空白final引用public BlankFinal(){j = 1; // 初始化空白finalp = new Poppet(1); // 初始化空白final引用}public BlankFinal(int x){j = x; // 初始化空白finalp = new Poppet(x); // 初始化空白final引用}public static void main(String[] args){new BlankFinal();new BlankFinal(47);} }(5)用final修飾參數,Java允許在參數列表中以聲明的方式將參數指明為final。這意味著你無法在方法中更改參數引用所指向的對象。
class Gizmo {public void spin(){} } public class FinalArguments {void with(final Gizmo g){//! g = new Gizmo(); // 錯誤,g是用final修飾的,無法將它指向另一個對象}void without(Gizmo g){g = new Gizmo(); // g不是final類型,可以將它指向新的對象g.spin();}// void f(final int i){ i++; } // 錯誤,i是用final修飾的,無法改變它的值。int g(final int i){ return i + 1; } // 正確,i的值沒有被改變public static void main(String[] args){FinalArguments bf = new FinalArguments();bf.with(null);bf.without(null);} }2、用final修飾方法
使用final方法的原因有兩個:
(1)把方法鎖定,以防任何繼承類修改它的含義。這是出于設計的考慮:想要確保在繼承中使方法行為保持不變,并且不會被覆蓋。
(2)效率,在Java的早期實現中,如果將一個方法指明為final,就是同意編譯器將針對該方法的所有調用都轉為內嵌調用。當編譯器發現一個final方法調用命令時,它會根據自己的謹慎判斷,跳過插入程序代碼這種正常方式而執行方法調用機制(將參數壓入棧,跳至方法代碼處并執行,然后跳回并清理棧中的參數,處理返回值),并且以方法體中的實際代碼的副本來替代方法調用。這將消除方法調用的開銷。
final和private:類中所有的private方法都隱式地指定為final的。由于無法取用private方法,所以也就無法覆蓋它。可以對private方法添加final修飾詞,但這并不能給該方法增加任何額外的意義。
3、用final修飾類
用final修飾的類無法被繼承,即它不能有子類。請注意:final的域可以根據個人的意愿選擇為是或不是final。不論類是否被定義為final,相同的規則都適用于定義為final的域。然而,由于final類禁止繼承,所以final類中所有的方法都會隱式指定為final的,因為無法覆蓋它們。在final類中可以給方法添加final修飾詞,但這不會增添任何意義。
深入理解final的好處
(1)final關鍵字提高了性能。JVM和Java應用都會緩存final變量。
(2)final變量可以安全的在多線程環境下進行共享,而不需要額外的同步開銷。
(3)使用final關鍵字,JVM會對方法、變量及類進行優化。
(4)創建不可變類要使用final關鍵字。不可變類是指它的對象一旦被創建了就不能被更改了。String是不可變類的代表。不可變類有很多好處,譬如它們的對象是只讀的,可以在多線程環境下安全的共享,不用額外的同步開銷等等。
總結
以上是生活随笔為你收集整理的Java之路:你真的了解final吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ArcGIS初步 系列视频教程
- 下一篇: 树莓派 armv几_如何在具有armv6