简体   繁体   中英

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.

I've realized that I can directly assign a value to a static variable at the definition time, like in:

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

Also, I have seen that you can use a static block, like in:

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:

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?

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.

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. 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.)

There is nothing wrong with using a setter (as per your third example) but it is doing something different. 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.


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:

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. The static block can be more complicated than a single assignment statement.


1 - I am being "loose" with the terminology here. It is actually the variables that are final not the objects.

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 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. 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. so that every time an object is created it might affect the other parts of your code.

among setting directly or in the static block, I personally prefer direct one because of it is more clear and readable by other users.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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