繁体   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