Java: When is a static initialization block useful

2019-01-10 00:38发布

问题:

What's the difference between initialization within a static block:

public class staticTest {

    static String s;
    static int n;
    static double d;

    static {
        s = "I'm static";
        n = 500;
        d = 4000.0001;
    }
    ...

And individual static initialization:

public class staticTest {

    static String s = "I'm static";
    static int n    = 500;
    static double d = 4000.0001;

    ....

回答1:

A static initialization blocks allows more complex initialization, for example using conditionals:

static double a;
static {
    if (SomeCondition) {
      a = 0;
    } else {
      a = 1;
    }
}

Or when more than just construction is required: when using a builder to create your instance, exception handling or work other than creating static fields is necessary.

A static initialization block also runs after the inline static initializers, so the following is valid:

static double a;
static double b = 1;

static {
    a = b * 4; // Evaluates to 4
}


回答2:

A typical usage:

private final static Set<String> SET = new HashSet<String>();

static {
    SET.add("value1");
    SET.add("value2");
    SET.add("value3");
}

How would you do it without static initializer?



回答3:

Exception handling during initialization is another reason. For example:

static URL url;
static {
    try {
        url = new URL("https://blahblah.com");
    }
    catch (MalformedURLException mue) {
        //log exception or handle otherwise
    }
}

This is useful for constructors that annoyingly throw checked exceptions, like above, or else more complex initialization logic that might be exception-prone.



回答4:

In your example, there is no difference; but often the initial value is more complex than is comfortably expressed in a single expression (e.g., it's a List<String> whose contents are best expressed by a for-loop; or it's a Method that might not exist, so exception-handlers are needed), and/or the static fields need to be set in a specific order.



回答5:

Sometimes you want to do more than just assign values to static variables. Since you cannot put arbitrary statements in the class body, you could use a static initializer block.



回答6:

static block can be used to initialize singleton instance, to prevent using synchronized getInstance() method.



回答7:

Technically, you could get away without it. Some prefer multiline initialisation code to go into a static method. I'm quite happy using a static initialiser for relatively simple multistatement initialisation.

Of course, I'd almost always make my statics final and point to an unmodifiable object.



回答8:

Static keyword (whether it's a variable or block) is belong to the class. So when the class is called, these variables or blocks are executed. So most of the initialisation will be done with the help of static keyword. As it is belong to the class itself, the class can directly accessed it, without creating an instance of the class.

Let's take an example, There is a shoe class in which there are several variables like colour, size, brand etc... And here if the shoe manufacture company has only one brand than we should initialise it as a static variable. So, when the shoe class is called and different types of shoes are manufactured (by creating an instance of the class) at that time colour and size will occupy memory whenever new shoe is created but here the brand is a common property for all shoes, so that it will occupy memory for once no matter how many shoes are manufactured.

Example:

    class Shoe {
    int size;
    String colour;
    static String brand = "Nike";

    public Shoe(int size, String colour) {
        super();
        this.size = size;
        this.colour = colour;
    }

    void displayShoe() {
        System.out.printf("%-2d %-8s %s %n",size,colour, brand);
    }

    public static void main(String args[]) {
        Shoe s1 = new Shoe(7, "Blue");
        Shoe s2 = new Shoe(8, "White");

        System.out.println("=================");
        s1.displayShoe();
        s2.displayShoe();
        System.out.println("=================");
    }
}


回答9:

You can use try/catch block inside static{} like below:

MyCode{

    static Scanner input = new Scanner(System.in);
    static boolean flag = true;
    static int B = input.nextInt();
    static int H = input.nextInt();

    static{
        try{
            if(B <= 0 || H <= 0){
                flag = false;
                throw new Exception("Breadth and height must be positive");
            }
        }catch(Exception e){
            System.out.println(e);
        }

    }
}

PS: Referred from this!



回答10:

The static code block enables to initialize the fields with more than instuction, initialize fields in a different order of the declarations and also could be used for conditional intialization.

More specifically,

static final String ab = a+b;
static final String a = "Hello,";
static final String b = ", world";

will not work because a and b are declared after ab.

However I could use a static init. block to overcome this.

static final String ab;
static final String a;
static final String b;

static {
  b = ", world";
  a = "Hello";
  ab = a + b;
}

static final String ab;
static final String a;
static final String b;

static {
  b = (...) ? ", world" : ", universe";
  a = "Hello";
  ab = a + b;
}


回答11:

We use constructors to initialize our instance variables(non-static variables, variables that belong to objects, not the class).

If you want to initialize class variables(static variables) and want to do it without creating an object(constructors can only be called when creating an object), then you need static blocks.

static Scanner input = new Scanner(System.in);
static int widht;
static int height;

static
{
    widht = input.nextInt();
    input.nextLine();
    height = input.nextInt();
    input.close();

    if ((widht < 0) || (height < 0))
    {
        System.out.println("java.lang.Exception: Width and height must be positive");
    }
    else
    {
        System.out.println("widht * height");
    }
}


回答12:

A static initialization block is useful if one, you wish to intialize specified class static types, prior to the class first use. Subsequent use will not invoke any static initialization blocks. It's the direct opposite of instance initializers, which initialize instance members.