簡體   English   中英

在 Java 語言中以一種或另一種方式初始化 static 變量的正確方法或潛在區別是什么?

[英]What's the proper way or underlying difference of initializing a static variable in one way or another in Java language?

我對初始化 static 變量的正確方法有點懷疑。

我意識到我可以在定義時直接為static變量賦值,例如:

public class MyClass {
  // Direct initialization
  public static int counter = 0;

另外,我看到您可以使用static塊,例如:

public class MyClass {
  public static int counter;

  static {
    counter = 0;
  }
}

甚至,我驚訝地看到,您還可以從 class 構造函數訪問static變量並從那里設置一個值,例如:

public class MyClass {
  public static int counter;

  public MyClass() {
    this.counter = 0;
  }

  public MyClass( int a ) {
    this.counter = a;
  }
}

我的問題是:在處理 static 變量時,使用一種或另一種類型的初始化的正確方法或潛在區別是什么?

我還編寫並執行了以下代碼,因此我可以意識到變量是如何隨着程序執行而被修改的。

public class StaticVariable {
    static int a = 0;

    public StaticVariable( int b ) {
        // The constructor parameter b is ignored
        System.out.println( "[Inside 1-parameter constructor] Current value of \"a\": " + a + " ." );
        System.out.println( "[Inside 1-parameter constructor] Value of \"a\" was increased in one ..." );
      a++;
    }

    public StaticVariable() {
        System.out.println( "[Inside parameterless constructor] Current value of \"a\": " + a + " ." );
        System.out.println( "[Inside parameterless constructor] Value of \"a\" was increased in one ..." );
      a++;
    }

    static {
        System.out.println( "[Inside static block] Initial value of \"a\": " + a + " ." );  
        System.out.println( "[Inside static block] Value of \"a\" was increased in one ..." );
      a++;
    }

    public static void main( String[] args ) {
        System.out.println( "[main method] Current value of \"a\": " + StaticVariable.a + " ." );
        StaticVariable object = new StaticVariable();
        System.out.println( "[main method] Current value of \"a\": " + StaticVariable.a + " ." );
        StaticVariable object2 = new StaticVariable( 10 );
        System.out.println( "[main method] Current value of \"a\": " + StaticVariable.a );
        System.out.println( "[main method] Directly setting value of \"a\" with 560" );
        StaticVariable.a = 560;
        System.out.println( "Updated value of \"a\": " + StaticVariable.a );
    }
}

提前致謝。

簡短回答:如果您需要使用static塊,請僅使用它們。

在您的前兩個示例中,沒有語義或性能差異,編寫代碼的正確方法是簡單的方法。

第三個例子在語義上是不同的。 設置器實際上並未初始化 static 變量。 它正在重新初始化變量。 (您可以在調用 setter 之前調用 getter,這將向您顯示真正的初始值;即零。)

使用 setter 沒有任何問題(根據您的第三個示例),但它正在做一些不同的事情。 如果您只想簡單地初始化為固定值,請不要這樣做。 用簡單的方法來做。

(最后一個例子似乎不恰當,所以我將忽略它。)

在某些情況下,不可能在單個表達式中執行必要的初始化。 (例如,可能需要執行一系列語句來填充 object,或捕獲並處理異常,或處理相互引用的final對象1。 )在這些情況下, static塊是一種可能的解決方案。


前兩種方法之間是否存在“潛在差異”?

我不這么認為。

static Foo foo = <expression>;   // where this is legal Java code

在語義上 100% 等價於:

static Foo foo;
static {
    foo = <expression>;
}

只是有些事情可以用 static 塊做,而用簡單的初始化程序是做不到的。 static 塊可能比單個賦值語句更復雜。


1 - 我在這里的術語“松散”。 它實際上是final的變量而不是對象。

第一種和第二種方法是等效的。 通常,您會發現第一種方法對於單個變量的簡單初始化更為常見。 但有時 static 塊中的初始化可以方便更復雜的情況,例如,將幾個元素添加到一個static變量的集合中,如下所示:

static List<String> list;
static {
  list = new ArrayList<>();
  list.add("hello");
  list.add("world");
}

至於您描述的第三個選項,即在實例化期間進行初始化,它將在每次創建 class 的新實例時重新初始化 static 變量。 可能最好避免這種情況。 我想不出我想要的情況。

Static 字段屬於 class 而不是對象,因此在構造函數中設置它們的值並不是一個好主意。 因此,每次創建 object 時,它都可能會影響代碼的其他部分。

在直接設置或在 static 塊中設置中,我個人更喜歡直接設置,因為它更清晰易讀。

暫無
暫無

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

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