java中的final怎么理解 final關(guān)鍵字的3種用法看完這篇全明白

final關(guān)鍵字在Java中有三種主要用法。1. 修飾變量:變量一旦被賦值不可更改,final成員變量需在聲明或構(gòu)造器中初始化,final局部變量只能賦值一次;2. 修飾方法:該方法不能被子類重寫,用于保護關(guān)鍵邏輯并可能提升性能;3. 修飾類:該類不能被繼承,用于構(gòu)建不可變類或防止設計破壞。此外,final可提高線程安全性和代碼可靠性,但final不等于完全不可變,要實現(xiàn)immutable對象還需滿足類不可繼承、成員變量不可修改等條件。

java中的final怎么理解 final關(guān)鍵字的3種用法看完這篇全明白

final關(guān)鍵字在Java中扮演著一個重要的角色,它用于表示“最終的”或“不可改變的”狀態(tài)。理解final對于編寫健壯、高效的代碼至關(guān)重要。簡單來說,final可以應用于變量、方法和類,分別有不同的含義。

java中的final怎么理解 final關(guān)鍵字的3種用法看完這篇全明白

final關(guān)鍵字主要有三種用法:修飾變量(包括成員變量和局部變量)、修飾方法和修飾類。每種用法都涉及到不同的語義和限制,理解這些限制對于編寫高質(zhì)量的Java代碼至關(guān)重要。

java中的final怎么理解 final關(guān)鍵字的3種用法看完這篇全明白

final修飾變量:不可變性的保證

final修飾變量時,意味著該變量一旦被賦值,其值就不能再被修改。這聽起來很簡單,但其中蘊含著一些微妙之處。

立即學習Java免費學習筆記(深入)”;

  • final成員變量: 必須在聲明時或者構(gòu)造器中進行初始化。這意味著,每個對象創(chuàng)建時,其final成員變量都必須有確定的值。如果一個類有多個構(gòu)造器,那么每個構(gòu)造器都必須確保所有final成員變量都被初始化。這可以避免出現(xiàn)未初始化的final變量,從而保證了對象狀態(tài)的完整性。

    java中的final怎么理解 final關(guān)鍵字的3種用法看完這篇全明白

    public class MyClass {     private final int x; // 必須初始化      public MyClass(int x) {         this.x = x; // 在構(gòu)造器中初始化     }      public int getX() {         return x;     } }

    值得注意的是,對于引用類型的final成員變量,final僅僅保證引用本身不可變,即不能指向另一個對象。但對象內(nèi)部的狀態(tài)是可以改變的。例如:

    public class MyClass {     private final List<String> myList;      public MyClass(List<String> list) {         this.myList = list; // 初始化為傳入的list     }      public void modifyList() {         myList.add("new element"); // 合法,因為只是修改了list的內(nèi)容     }      public List<String> getMyList() {         return myList;     }  }

    在這個例子中,myList是final的,但我們可以通過modifyList()方法修改列表的內(nèi)容。如果需要完全的不可變性,需要使用不可變集合(如guava的ImmutableList)或者手動創(chuàng)建對象的深拷貝。

  • final局部變量: 可以在聲明后賦值,但只能賦值一次。這在Lambda表達式和匿名內(nèi)部類中尤其有用,因為它們只能訪問final或 effectively final的局部變量。

    public void myMethod() {     final int y;     y = 10; // 第一次賦值     // y = 20; // 錯誤:不能再次賦值 }

    “effectively final” 是指變量雖然沒有被聲明為final,但在初始化后沒有被修改過,因此在lambda表達式或匿名內(nèi)部類中可以被當作final變量使用。

final修飾方法:阻止方法重寫

當final修飾一個方法時,意味著該方法不能被子類重寫(override)。這通常用于防止子類修改父類的關(guān)鍵邏輯。

public class Parent {     public final void myMethod() {         System.out.println("Parent's myMethod");     } }  public class Child extends Parent {     // @Override     // public void myMethod() { // 編譯錯誤:不能重寫final方法     //     System.out.println("Child's myMethod");     // } }

final方法可以提高代碼的安全性,防止子類意外地修改父類的行為。另外,final方法在某些情況下可以提高性能,因為編譯器可以對final方法進行內(nèi)聯(lián)優(yōu)化。

final修飾類:禁止繼承

當final修飾一個類時,意味著該類不能被繼承。這通常用于創(chuàng)建不可變的類,或者防止子類破壞類的設計。

public final class ImmutableClass {     private final int x;      public ImmutableClass(int x) {         this.x = x;     }      public int getX() {         return x;     } }  // class SubClass extends ImmutableClass { // 編譯錯誤:不能繼承final類 // // }

string類就是一個典型的final類。它的不可變性使得它可以安全地在多線程環(huán)境中使用,并且可以作為HashMap的鍵。

為什么使用final?final關(guān)鍵字的好處

使用final關(guān)鍵字有很多好處,不僅僅是為了防止修改。

  • 不可變性: final可以保證變量、方法或類的狀態(tài)不可變,這可以提高代碼的可靠性和安全性。不可變對象更容易理解和調(diào)試,并且可以安全地在多線程環(huán)境中使用。
  • 性能優(yōu)化 final方法允許編譯器進行內(nèi)聯(lián)優(yōu)化,這可以提高代碼的執(zhí)行效率。
  • 設計約束: final可以強制執(zhí)行設計約束,防止子類修改父類的關(guān)鍵邏輯或破壞類的設計。
  • 線程安全: final變量是線程安全的,因為它們的值在初始化后不會被修改。

final和immutable有什么區(qū)別

雖然final可以用于創(chuàng)建不可變對象,但final本身并不等同于immutable。final只是保證變量的引用不可變,而immutable則要求對象的狀態(tài)在創(chuàng)建后不能被修改。

一個類要成為immutable,需要滿足以下條件:

  1. 類本身是final的,防止被繼承。
  2. 所有的成員變量都是final的。
  3. 所有的成員變量都是immutable的,或者如果成員變量是可變的,則不能直接訪問,必須通過防御性拷貝來保護。
  4. 沒有提供修改對象狀態(tài)的方法(setter方法)。
public final class ImmutablePerson {     private final String name;     private final int age;     private final List<String> hobbies; // 必須是不可變集合或者深拷貝      public ImmutablePerson(String name, int age, List<String> hobbies) {         this.name = name;         this.age = age;         this.hobbies = new ArrayList<>(hobbies); // 防御性拷貝     }      public String getName() {         return name;     }      public int getAge() {         return age;     }      public List<String> getHobbies() {         return new ArrayList<>(hobbies); // 返回防御性拷貝     } }

在這個例子中,ImmutablePerson類是immutable的,因為它滿足了上述所有條件。

final關(guān)鍵字在實際項目中的應用場景

在實際項目中,final關(guān)鍵字被廣泛使用。

  • 配置常量 使用final Static修飾的常量,用于存儲配置信息。

    public class Config {     public static final String DEFAULT_NAME = "default";     public static final int MAX_CONNECTIONS = 100; }
  • 緩存結(jié)果: 使用final修飾的變量,用于緩存計算結(jié)果,避免重復計算。

    public class CacheExample {     private final int result;      public CacheExample(int input) {         this.result = calculate(input);     }      private int calculate(int input) {         // 復雜的計算邏輯         return input * 2;     }      public int getResult() {         return result;     } }
  • 構(gòu)建不可變對象: 使用final修飾的類和成員變量,用于構(gòu)建不可變對象,提高代碼的可靠性和安全性。例如,Guava的ImmutableList、ImmutableMap等。

  • 模板方法模式: 在模板方法模式中,父類定義算法的骨架,子類實現(xiàn)具體的步驟。可以使用final修飾模板方法,防止子類修改算法的骨架。

    public abstract class AbstractTemplate {     public final void templateMethod() {         step1();         step2();         step3();     }      protected abstract void step1();     protected abstract void step2();     protected abstract void step3(); }

final影響性能嗎?

理論上,final方法可以允許編譯器進行內(nèi)聯(lián)優(yōu)化,從而提高性能。但在實際應用中,這種優(yōu)化效果并不總是明顯的。現(xiàn)代jvm已經(jīng)非常智能,即使沒有final關(guān)鍵字,也可以對一些方法進行內(nèi)聯(lián)優(yōu)化。

過度的使用final關(guān)鍵字可能會使代碼變得難以維護,因此需要在性能和可維護性之間進行權(quán)衡。通常情況下,只有在性能瓶頸的代碼中才需要考慮使用final關(guān)鍵字進行優(yōu)化。

總而言之,理解final關(guān)鍵字的各種用法及其背后的設計思想,對于編寫高質(zhì)量的Java代碼至關(guān)重要。正確地使用final關(guān)鍵字可以提高代碼的可靠性、安全性、可維護性和性能。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊7 分享