简体   繁体   English

在 Java 语言中以一种或另一种方式初始化 static 变量的正确方法或潜在区别是什么?

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

I am a little bit doubtful about the proper way of initializing static variables.我对初始化 static 变量的正确方法有点怀疑。

I've realized that I can directly assign a value to a static variable at the definition time, like in:我意识到我可以在定义时直接为static变量赋值,例如:

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

Also, I have seen that you can use a static block, like in:另外,我看到您可以使用static块,例如:

public class MyClass {
  public static int counter;

  static {
    counter = 0;
  }
}

Even, I have surprisingly seen that you can also access static variables from class constructors and set them a value from there, like in:甚至,我惊讶地看到,您还可以从 class 构造函数访问static变量并从那里设置一个值,例如:

public class MyClass {
  public static int counter;

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

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

My question is: What's the proper way or underlying difference among using one or another type of initialization when dealing with static variables?我的问题是:在处理 static 变量时,使用一种或另一种类型的初始化的正确方法或潜在区别是什么?

I have also wrote and executed the following code, so I could realize how the variable is being modified along the program execution.我还编写并执行了以下代码,因此我可以意识到变量是如何随着程序执行而被修改的。

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 );
    }
}

Thanks in advance.提前致谢。

Short answer: only use static blocks if you need to use them.简短回答:如果您需要使用static块,请仅使用它们。

In your first two examples, there is no semantic or performance difference, and the proper way to write the code is the simple way.在您的前两个示例中,没有语义或性能差异,编写代码的正确方法是简单的方法。

The third example is semantically different.第三个例子在语义上是不同的。 The setter is not actually initializing the static variable.设置器实际上并未初始化 static 变量。 It is re-initializing the variable.它正在重新初始化变量。 (You can call the getter before calling the setter, and that will show you the real initial value; ie zero.) (您可以在调用 setter 之前调用 getter,这将向您显示真正的初始值;即零。)

There is nothing wrong with using a setter (as per your third example) but it is doing something different.使用 setter 没有任何问题(根据您的第三个示例),但它正在做一些不同的事情。 If you just want a simple initialization to a fixed value, don't do it this way.如果您只想简单地初始化为固定值,请不要这样做。 Do it the simple way.用简单的方法来做。

(The final example doesn't appear to be apropos, so I will ignore it.) (最后一个例子似乎不恰当,所以我将忽略它。)

In some cases it is not possible to perform the necessary initialization in a single expression.在某些情况下,不可能在单个表达式中执行必要的初始化。 (For example, it may be necessary to execute a sequence of statements to populate an object, or catch and handle an exception, or deal with final objects 1 that reference each other.) In these cases, a static block is a possible solutions. (例如,可能需要执行一系列语句来填充 object,或捕获并处理异常,或处理相互引用的final对象1。 )在这些情况下, static块是一种可能的解决方案。


Is there an "underlying difference" between the first two approaches?前两种方法之间是否存在“潜在差异”?

I don't think so.我不这么认为。

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

is 100% semantically equivalent to:在语义上 100% 等价于:

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

It is just that there are some things that you can do with a static block that you can't do with a simple initializer.只是有些事情可以用 static 块做,而用简单的初始化程序是做不到的。 The static block can be more complicated than a single assignment statement. static 块可能比单个赋值语句更复杂。


1 - I am being "loose" with the terminology here. 1 - 我在这里的术语“松散”。 It is actually the variables that are final not the objects.它实际上是final的变量而不是对象。

The first and second approaches are equivalent.第一种和第二种方法是等效的。 Typically you will find the first approach to be much more common for simple initializations of a single variable.通常,您会发现第一种方法对于单个变量的简单初始化更为常见。 But sometimes static initialization in a block can be convenient for more complicated situations, for example, adding several elements to a collection which is a static variable, as in:但有时 static 块中的初始化可以方便更复杂的情况,例如,将几个元素添加到一个static变量的集合中,如下所示:

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

As for the third option you describe, initializing during instantiation, it will reinitialize the static variable each time a new instance of the class is created.至于您描述的第三个选项,即在实例化期间进行初始化,它将在每次创建 class 的新实例时重新初始化 static 变量。 Probably best to avoid this.可能最好避免这种情况。 I can't think of a situation where I would have wanted that.我想不出我想要的情况。

Static fields belong to class not the objects, so it is not such a good idea to set their value in constructors. Static 字段属于 class 而不是对象,因此在构造函数中设置它们的值并不是一个好主意。 so that every time an object is created it might affect the other parts of your code.因此,每次创建 object 时,它都可能会影响代码的其他部分。

among setting directly or in the static block, I personally prefer direct one because of it is more clear and readable by other users.在直接设置或在 static 块中设置中,我个人更喜欢直接设置,因为它更清晰易读。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM