Static Initialization Blocks
Asked Answered
T

14

312

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 {...}?

Theomania answered 10/3, 2010 at 20:37 Comment(2)
Minor feedback, but it would help if you could please state your assumptions clearly, and hence clarify which answer is correct. when i first read your question, i mis-understood and thought you knew the difference between {...} vs static {...}. (in which case Jon Skeet definitely answered your question way better)Deanadeanda
This question is very unclear; you have the answerers scrambling and making lots of long-winded conjectures about what you meant. How about explicitly writing out the example static initialization block you have in mind and your alternative, so that people have something clear to answer?Appellation
W
512

The non-static block:

{
    // Do Something...
}

Gets called every time an instance of the class is constructed. The static block only gets called once, when the class itself is initialized, no matter how many objects of that type you create.

Example:

public class Test {

    static{
        System.out.println("Static");
    }

    {
        System.out.println("Non-static block");
    }

    public static void main(String[] args) {
        Test t = new Test();
        Test t2 = new Test();
    }
}

This prints:

Static
Non-static block
Non-static block
Wherever answered 10/3, 2010 at 20:48 Comment(7)
It answers the question: "This gets called everytime the class is constructed. The static block only gets called once, no matter how many objects of that type you create."Dedie
For the curious reader, the non-static block is actually copied by the Java compiler into every constructor the class has (source). So it is still the constructor's job to initialize fields.Gogetter
Why is this answer suddenly getting downvoted? You might disagree about this being the accepted answer, but it is certainly not in any way wrong or misleading. It is simply trying to help the understanding of these language constructs with a simple example.Wherever
Maybe it isn't a real answer to the question, but answers my questions reading the real answer. :-) This is because it gets an up. And also the real answer gets an up, because so is it justiful.Dextrose
If you think the accepted answer is the "wrong" answer, it may be that the OP has not phrased their question clearly.Humbert
Note on the execution order: static block is always called first regardless of its position in the code.Fourth
How JVM knows that class is constructed once or more than once?Waldenses
B
145

If they weren't in a static initialization block, where would they be? How would you declare a variable which was only meant to be local for the purposes of initialization, and distinguish it from a field? For example, how would you want to write:

public class Foo {
    private static final int widgets;

    static {
        int first = Widgets.getFirstCount();
        int second = Widgets.getSecondCount();
        // Imagine more complex logic here which really used first/second
        widgets = first + second;
    }
}

If first and second weren't in a block, they'd look like fields. If they were in a block without static in front of it, that would count as an instance initialization block instead of a static initialization block, so it would be executed once per constructed instance rather than once in total.

Now in this particular case, you could use a static method instead:

public class Foo {
    private static final int widgets = getWidgets();

    static int getWidgets() {
        int first = Widgets.getFirstCount();
        int second = Widgets.getSecondCount();
        // Imagine more complex logic here which really used first/second
        return first + second;
    }
}

... but that doesn't work when there are multiple variables you wish to assign within the same block, or none (e.g. if you just want to log something - or maybe initialize a native library).

Bushire answered 10/3, 2010 at 20:40 Comment(6)
Does the static block happen before static variables are assigned or after? private static int widgets = 0; static{widgets = 2;}Ochre
Was curious about if the static block happen before static variables are assigned or after. e.g. private static int widgets = 0; static{widgets = 2;} Found out that the '=' assignment happens in order, which means the '=' put first will be assigned first. The above example will give 'widgets' a value of 2. (P.S. didn't know that comments can only be edited in 5 min...)Ochre
@WeishiZeng: Yes, this is as documented in docs.oracle.com/javase/specs/jls/se8/html/… - point 9.Bushire
But couldn't you also use a private static method that has the exact same code as the the static initialization block and assign widgets to the private static method?Season
@Zachary: Do you mean returning the value, and assigning the result of the method call? If so, yes - when you are assigning to exactly one variable as a result of the block. Will edit my answer with details in about 7 hours...Bushire
@JonSkeet okay thanks that answered a major question I had about when you had to use static initialization blocks and private static methods for initialization of static fields.Season
H
109

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.

Historic answered 10/3, 2010 at 20:40 Comment(4)
For that particular example sometimes the double brace pattern is been "abused" :)Snap
It can be abused, but on the other hand it does clean up some messes, and makes some kinds of code a little more "solid." I program in Erlang for fun, and you get hooked on not needing local variables :-)Historic
<< 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. >> (Which "Pointy" mentioned in above answer) this is very important point to be noted when it comes to static block execution.Mishmash
Can we do this with using InitializingBean in after afterPropertiesSet method ?Australopithecus
S
51

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.

Snap answered 10/3, 2010 at 21:20 Comment(4)
Herein lies dangerous voodoo... static initializers are run in the synthetic clinit() method, which is implicitly synchronized. This means that the JVM will acquire a lock on the classfile in question. This can lead to deadlock in multithreaded environments if two classes try to load each other, and each one starts loading in a different thread. See www-01.ibm.com/support/docview.wss?uid=swg1IV48872Chapbook
@Ajax: I'd consider this a bug in either the JDBC driver in question, or in the application code responsible for loading it. Usually, in case of decent JDBC drivers, as long as you load it only once applicationwide during application's startup, there's nothing at matter.Snap
It certainly would be a bug but not entirely the fault of the JDBC driver, however. Maybe the driver innocently has its own static initializers, and maybe you innocently initialize this class along with some others in your app, and, oh no, some unexpected classes cyclically load each other, and now your app deadlocks. I discovered this thanks to deadlock between java.awt.AWTEvent and sun.util.logging.PlatformLogger. I only touched AWTEvent to tell it to run headless, and some other lib wound up loading PlatformLogger... which AWTEvent also loads.Chapbook
Both classes wound up synchronized on different threads, and my build deadlocked about 1/150 runs. So, I am now a lot more careful on classloading in static blocks. In the case I mentioned above, using a deferred provider pattern where I could create an interim provider class immediately (with no chance of deadlock), initialize the field, and then when it is actually accessed (in a non-synchronized field access), then I actually load the classes that can cause the deadlock.Chapbook
A
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.

Autarch answered 7/9, 2012 at 11:43 Comment(0)
D
12

I would say static block is just syntactic sugar. There is nothing you could do with static block and not with anything else.

To re-use some examples posted here.

This piece of code could be re-written without using static initialiser.

Method #1: With static

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

Method #2: Without static

private static final HashMap<String, String> MAP = getMap();
private static HashMap<String, String> getMap()
{
    HashMap<String, String> ret = new HashMap<>();
    ret.put("banana", "honey");
    ret.put("peanut butter", "jelly");
    ret.put("rice", "beans");
    return ret;
}
Damaraland answered 28/2, 2013 at 5:20 Comment(0)
H
9

You can execute bits of code once for a class before an object is constructed in the static blocks.

E.g.

class A {
  static int var1 = 6;
  static int var2 = 9;
  static int var3;
  static long var4;

  static Date date1;
  static Date date2;

  static {
    date1 = new Date();

    for(int cnt = 0; cnt < var2; cnt++){
      var3 += var1;
    }

    System.out.println("End first static init: " + new Date());
  }
}
Hootman answered 10/3, 2010 at 20:40 Comment(0)
M
7

It is a common misconception to think that a static block has only access to static fields. For this I would like to show below piece of code that I quite often use in real-life projects (copied partially from another answer in a slightly different context):

public enum Language { 
  ENGLISH("eng", "en", "en_GB", "en_US"),   
  GERMAN("de", "ge"),   
  CROATIAN("hr", "cro"),   
  RUSSIAN("ru"),
  BELGIAN("be",";-)");

  static final private Map<String,Language> ALIAS_MAP = new HashMap<String,Language>(); 
  static { 
    for (Language l:Language.values()) { 
      // ignoring the case by normalizing to uppercase
      ALIAS_MAP.put(l.name().toUpperCase(),l); 
      for (String alias:l.aliases) ALIAS_MAP.put(alias.toUpperCase(),l); 
    } 
  } 

  static public boolean has(String value) { 
    // ignoring the case by normalizing to uppercase
    return ALIAS_MAP.containsKey(value.toUpper()); 
  } 

  static public Language fromString(String value) { 
    if (value == null) throw new NullPointerException("alias null"); 
    Language l = ALIAS_MAP.get(value); 
    if (l == null) throw new IllegalArgumentException("Not an alias: "+value); 
    return l; 
  } 

  private List<String> aliases; 
  private Language(String... aliases) { 
    this.aliases = Arrays.asList(aliases); 
  } 
} 

Here the initializer is used to maintain an index (ALIAS_MAP), to map a set of aliases back to the original enum type. It is intended as an extension to the built-in valueOf method provided by the Enum itself.

As you can see, the static initializer accesses even the private field aliases. It is important to understand that the static block already has access to the Enum value instances (e.g. ENGLISH). This is because the order of initialization and execution in the case of Enum types, just as if the static private fields have been initialized with instances before the static blocks have been called:

  1. The Enum constants which are implicit static fields. This requires the Enum constructor and instance blocks, and instance initialization to occur first as well.
  2. static block and initialization of static fields in the order of occurrence.

This out-of-order initialization (constructor before static block) is important to note. It also happens when we initialize static fields with the instances similarly to a Singleton (simplifications made):

public class Foo {
  static { System.out.println("Static Block 1"); }
  public static final Foo FOO = new Foo();
  static { System.out.println("Static Block 2"); }
  public Foo() { System.out.println("Constructor"); }
  static public void main(String p[]) {
    System.out.println("In Main");
    new Foo();
  }
}

What we see is the following output:

Static Block 1
Constructor
Static Block 2
In Main
Constructor

Clear is that the static initialization actually can happen before the constructor, and even after:

Simply accessing Foo in the main method, causes the class to be loaded and the static initialization to start. But as part of the Static initialization we again call the constructors for the static fields, after which it resumes static initialization, and completes the constructor called from within the main method. Rather complex situation for which I hope that in normal coding we would not have to deal with.

For more info on this see the book "Effective Java".

Madrepore answered 15/6, 2015 at 4:31 Comment(5)
Having access to aliases does not mean the static block can access non static members. aliases is accessed through the Language values returned by the /static/ values() method. As you mention, the fact that the enum variables are already available at that point is the unusual bit - non static members of regular classes would not be accessible in this situation.Revenue
The static block is still accessing only static fields (in the case of your enum ENGLISH,GERMAN, ...) which in this case are objects. Since the static fields are objects themselves, you can access the static object's instance field.Undercroft
class Foo { static final Foo Inst1; static final Foo Inst2; static{ Inst1 = new Foo("Inst1"); Inst2 = new Foo("Inst2"); } static { System.out.println("Inst1: " + Inst1.member); System.out.println("Inst2: " + Inst2.member); } private final String member; private Foo(String member){ this.member = member; } } The above code is no different from the enum example and still allows access of instance variable inside the static blockUndercroft
@SwamiPR indeed it compiles, to my surprise, and I have to agree that the code is in principle no different. I have to reread the Java spec, I feel that there is something I missed. Good response back, thanks.Madrepore
@SwamiPR The issue really is that we should be using an Enum. It is the best way to guarantee that we are pointing to singular instances' - see here. And to your points, I have made several updates.Madrepore
S
4

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
 }

}
Stockmon answered 29/7, 2013 at 3:51 Comment(0)
H
3

If your static variables need to be set at runtime then a static {...} block is very helpful.

For example, if you need to set the static member to a value which is stored in a config file or database.

Also useful when you want to add values to a static Map member as you can't add these values in the initial member declaration.

Hyperthyroidism answered 10/3, 2010 at 20:40 Comment(0)
T
1

It is important to understand that classes are instantiated from java.class.Class during runtime. That is when static blocks are executed, which allows you to execute code without instantiating a class:

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

The result is myInt is 1 printed to the console.

Theravada answered 20/10, 2016 at 16:2 Comment(0)
L
0

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.

Loudish answered 3/8, 2016 at 14:18 Comment(0)
P
-1

static block is used for any technology to initialize static data member in dynamic way,or we can say for the dynamic initialization of static data member static block is being used..Because for non static data member initialization we have constructor but we do not have any place where we can dynamically initialize static data member

Eg:-class Solution{
         // static int x=10;
           static int x;
       static{
        try{
          x=System.out.println();
          }
         catch(Exception e){}
        }
       }

     class Solution1{
      public static void main(String a[]){
      System.out.println(Solution.x);
        }
        }

Now my static int x will initialize dynamically ..Bcoz when compiler will go to Solution.x it will load Solution Class and static block load at class loading time..So we can able to dynamically initialize that static data member..

}

Protanopia answered 14/10, 2012 at 16:45 Comment(0)
S
-2
static int B,H;
static boolean flag = true;
static{
    Scanner scan = new Scanner(System.in);
    B = scan.nextInt();
    scan.nextLine();
    H = scan.nextInt();

    if(B < 0 || H < 0){
        flag = false;
        System.out.println("java.lang.Exception: Breadth and height must be positive");
    } 
}
Secede answered 10/5, 2019 at 5:22 Comment(1)
Glad to delete my downvote if you add a description about what your code is doing and how it answers the question. More info here on how to write a good answer. Thanks!Fledgy

© 2022 - 2024 — McMap. All rights reserved.