簡體   English   中英

Java中靜態變量和最終靜態變量之間的區別

[英]Difference between a static and a final static variable in Java

通常,特別是 final 靜態成員,變量(當然也可以是靜態 final,它們可以按任意順序使用而不會重疊含義)廣泛用於 Java 中的接口,以定義實現類的協議行為,這意味着實現類(繼承)一個接口必須包含該接口的所有成員。


我無法區分最終最終靜態成員。 最后一個靜態成員是聲明為 final 的靜態成員還是其他什么? 應該在哪些特定情況下專門使用它們?


永遠不能在方法內部聲明靜態變量或最終靜態變量,既不能在靜態方法內部,也不能在實例方法內部。 為什么?

相應地,以下代碼段將不會被編譯,並且如果嘗試編譯它,編譯器將發出編譯時錯誤。

public static void main(String args[])
{
    final int a=0;  //ok

    int b=1;  //ok

    static int c=2;  //wrong

    final static int x=0;  //wrong
}

您正在大量混合許多不同的概念。 甚至標題中的問題也不對應正文中的問題。

無論如何,這些是您正在混淆的概念:

  • 變量
  • 最終變量
  • 領域
  • 最終字段
  • 靜態字段
  • 最終靜態字段

關鍵字static僅對字段有意義,但在您展示的代碼中,您試圖在函數中使用它,在該函數中您不能聲明字段(字段是類的成員;變量在方法中聲明)。

讓我們嘗試快速描述它們。

  1. 變量在方法中聲明,並用作某種可變的本地存儲int x; x = 5; x++

  2. final 變量也在方法中聲明,並用作不可變的本地存儲final int y; y = 0; y++; // won't compile )。 它們對於捕獲某人試圖修改不應修改的內容的錯誤很有用。 我個人將大部分局部變量和方法參數final 此外,當您從內部匿名類引用它們時,它們是必需的。 在某些編程語言中,唯一一種變量是不可變變量(在其他語言中,“默認”類型的變量是不可變變量)——作為練習,嘗試找出如何編寫一個循環來運行初始化后不允許更改任何內容的指定次數! (例如,嘗試僅使用最終變量解決fizzbuzz 問題!)。

  3. 字段定義了對象可變狀態,並在類中聲明( class x { int myField; } )。

  4. final 字段定義了對象不可變狀態,在類中聲明並且必須在構造函數完成之前初始化( class x { final int myField = 5; } )。 它們不能被修改。 它們在執行多線程時非常有用,因為它們具有與線程之間共享對象相關的特殊屬性(您可以保證每個線程都會看到對象的最終字段的正確初始化值,如果在構造函數完成后共享對象,並且即使它與數據競爭共享)。 如果你想要另一個練習,嘗試只使用 final 字段再次解決fizzbuzz ,沒有其他字段,沒有任何變量或方法參數(顯然,你可以在構造函數中聲明參數,但僅此而已!)。

  5. 靜態字段在任何類的所有實例之間共享 您可以將它們視為某種全局可變存儲( class x { static int globalField = 5; } )。 最簡單(通常也無用)的例子是計算對象的實例數(即class x { static int count = 0; x() { count++; } } ,這里構造函數每次調用時都會增加計數,即,每次您使用new x()創建x的實例時。 請注意,與 final 字段不同,它們本質上不是線程安全的; 換句話說,如果您從不同的線程進行實例化,那么使用上面的代碼肯定會得到錯誤的x實例計數; 為了使它正確,您必須為此目的添加一些同步機制或使用一些專門的類,但這是另一個問題(實際上,它可能是整本書的主題)。

  6. final 靜態字段全局常量class MyConstants { public static final double PI = 3.1415926535897932384626433; } )。

還有許多其他微妙的特性(例如:編譯器可以自由地將最終靜態字段的引用直接替換為其值,這使得反射對此類字段無用;最終字段實際上可能會被反射修改,但這很容易出錯;和等等),但我想說在進一步挖掘之前你還有很長的路要走。

最后,還有其他關鍵字可以與字段一起使用,例如transientvolatile和訪問級別( publicprotectedprivate )。 但這是另一個問題(實際上,如果您想詢問他們,還有許多其他問題,我會說)。

靜態成員是那些無需創建對象即可訪問的成員。 這意味着那些是類成員,與任何實例無關。 因此不能在方法中定義。

換句話說final是一個常數(如在 C 中)。 您可以在方法內部以及類級別擁有最終變量。 如果你把 final 設為靜態,它就會變成“一個常量的類成員”

final 關鍵字僅表示“無法更改”。它可以與方法中的字段和變量一起使用。當變量被聲明為 final 時,嘗試更改該變量將導致編譯時錯誤。例如,如果我聲明作為最終 int x = 12 的變量; 試圖增加 x 即 (++x) 會產生一個錯誤。簡而言之,用 final 使一個值成為一個常數。 另一方面,靜態只能應用於字段,不能應用於方法。最終靜態的字段只有一個存儲空間。最終表示它是一個常量(不能更改),靜態表示它只有一個。

在Java中,靜態變量是屬於類而不是類的對象,同一個類的不同實例將包含相同的靜態變量值。

最終變量是一個在初始化后,在類的實例化(創建一個對象)之后不能在程序中更改的變量。 但是,如果在創建同一類的另一個對象后傳遞不同的值,則這與對象不同。

final static 意味着該變量屬於該類,並且一旦初始化就不能更改。 因此,可以在同一類的不同實例中訪問相同的值。

我無法區分最終和最終靜態成員。 最后一個靜態成員是聲明為 final 的靜態成員還是其他什么? 應該在哪些特定情況下專門使用它們?

當您希望它是static時,請使用final static static 當您不希望它是static時,請使用final (非靜態)。

永遠不能在方法內部聲明靜態變量或最終靜態變量,既不能在靜態方法內部,也不能在實例方法內部。 為什么?

設計決策。 如果不詢問 James Gosling,就無法回答這個問題。

相應地,以下代碼段將不會被編譯,並且如果嘗試編譯它,編譯器將發出編譯時錯誤。

因為它違反了你剛才描述的規則。

只是在@Bruno Reis 的答案中添加一個次要信息,我試圖完成答案,因為他談到了在構造函數結束之前初始化最終字段的重要條件,最終靜態字段也必須在靜態塊執行完成之前初始化.

你不能在靜態塊中聲明靜態字段,靜態字段只能屬於一個類,因此編譯器錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM