Static Initialization Blocks

2018-12-31 05:56发布

As far as I understood the "static initialization block" is used to set values of static field if it cannot be done in one line.

But I do not understand why we need a special block for that. For example we declare a field as static (without a value assignment). And then write several lines of the code which generate and assign a value to the above declared static field.

Why do we need this lines in a special block like: static {...}?

13条回答
栀子花@的思念
2楼-- · 2018-12-31 06:12

It's also useful when you actually don't want to assign the value to anything, such as loading some class only once during runtime.

E.g.

static {
    try {
        Class.forName("com.example.jdbc.Driver");
    } catch (ClassNotFoundException e) {
        throw new ExceptionInInitializerError("Cannot load JDBC driver.", e);
    }
}

Hey, there's another benefit, you can use it to handle exceptions. Imagine that getStuff() here throws an Exception which really belongs in a catch block:

private static Object stuff = getStuff(); // Won't compile: unhandled exception.

then a static initializer is useful here. You can handle the exception there.

Another example is to do stuff afterwards which can't be done during assigning:

private static Properties config = new Properties();

static {
    try { 
        config.load(Thread.currentThread().getClassLoader().getResourceAsStream("config.properties");
    } catch (IOException e) {
        throw new ExceptionInInitializerError("Cannot load properties file.", e);
    }
}

To come back to the JDBC driver example, any decent JDBC driver itself also makes use of the static initializer to register itself in the DriverManager. Also see this and this answer.

查看更多
不流泪的眼
3楼-- · 2018-12-31 06:12

There are a few actual reasons that it is required to exist:

  1. initializing static final members whose initialization might throw an exception
  2. initializing static final members with calculated values

People tend to use static {} blocks as a convenient way to initialize things that the class depends on within the runtime as well - such as ensuring that particular class is loaded (e.g., JDBC drivers). That can be done in other ways; however, the two things that I mention above can only be done with a construct like the static {} block.

查看更多
听够珍惜
4楼-- · 2018-12-31 06:12

So you have a static field (it's also called "class variable" because it belongs to the class rather than to an instance of the class; in other words it's associated with the class rather than with any object) and you want to initialize it. So if you do NOT want to create an instance of this class and you want to manipulate this static field, you can do it in three ways:

1- Just initialize it when you declare the variable:

static int x = 3;

2- Have a static initializing block:

static int x;

static {
 x=3;
}

3- Have a class method (static method) that accesses the class variable and initializes it: this is the alternative to the above static block; you can write a private static method:

public static int x=initializeX();

private static int initializeX(){
 return 3;
}

Now why would you use static initializing block instead of static methods?

It's really up to what you need in your program. But you have to know that static initializing block is called once and the only advantage of the class method is that they can be reused later if you need to reinitialize the class variable.

let's say you have a complex array in your program. You initialize it (using for loop for example) and then the values in this array will change throughout the program but then at some point you want to reinitialize it (go back to the initial value). In this case you can call the private static method. In case you do not need in your program to reinitialize the values, you can just use the static block and no need for a static method since you're not gonna use it later in the program.

Note: the static blocks are called in the order they appear in the code.

Example 1:

class A{
 public static int a =f();

// this is a static method
 private static int f(){
  return 3;
 }

// this is a static block
 static {
  a=5;
 }

 public static void main(String args[]) {
// As I mentioned, you do not need to create an instance of the class to use the class variable
  System.out.print(A.a); // this will print 5
 }

}

Example 2:

class A{
 static {
  a=5;
 }
 public static int a =f();

 private static int f(){
  return 3;
 }

 public static void main(String args[]) {
  System.out.print(A.a); // this will print 3
 }

}
查看更多
谁念西风独自凉
5楼-- · 2018-12-31 06:15

As supplementary, like @Pointy said

The code in the "static" section(s) will be executed at class load time, before any instances of the class are constructed (and before any static methods are called from elsewhere).

It's supposed to add System.loadLibrary("I_am_native_library") into static block.

static{
    System.loadLibrary("I_am_a_library");
}

It will guarantee no native method be called before the related library is loaded into memory.

According to loadLibrary from oracle:

If this method is called more than once with the same library name, the second and subsequent calls are ignored.

So quite unexpectedly, putting System.loadLibrary is not used to avoid library be loaded multi-times.

查看更多
孤独总比滥情好
6楼-- · 2018-12-31 06:19

Here's an example:

  private static final HashMap<String, String> MAP = new HashMap<String, String>();
  static {
    MAP.put("banana", "honey");
    MAP.put("peanut butter", "jelly");
    MAP.put("rice", "beans");
  }

The code in the "static" section(s) will be executed at class load time, before any instances of the class are constructed (and before any static methods are called from elsewhere). That way you can make sure that the class resources are all ready to use.

It's also possible to have non-static initializer blocks. Those act like extensions to the set of constructor methods defined for the class. They look just like static initializer blocks, except the keyword "static" is left off.

查看更多
谁念西风独自凉
7楼-- · 2018-12-31 06:23

You first need to understand that your application classes themselves are instantiated to java.class.Class objects during runtime. This is when your static blocks are ran. So you can actually do this:

public class Main {

    private static int myInt;

    static {
        myInt = 1;
        System.out.println("myInt is 1");
    }

    //  needed only to run this class
    public static void main(String[] args) {
    }

}

and it would print "myInt is 1" to console. Note that I haven't instantiated any class.

查看更多
登录 后发表回答