14

Sorry for the bad title, but I found the code listed below on mkyoung.com and was wondering what this code does. Is this a way in Java to set some default value into a variable?

public class LanguageBean implements Serializable{
    private static Map<String,Object> countries;
    static{
        countries = new LinkedHashMap<String,Object>();
        countries.put("English", Locale.ENGLISH); //label, value
        countries.put("Chinese", Locale.SIMPLIFIED_CHINESE);
    }
}
Melauki Mawi
  • 257
  • 1
  • 8

6 Answers6

25

This bit declares a static field:

private static Map<String,Object> countries;

So it's accessible directly on the class, e.g. LanguageBean.countries (or just countries), but only from code within the class, because it's private.

This bit is a static initializer:

static{
    countries = new LinkedHashMap<String,Object>();
    countries.put("English", Locale.ENGLISH); //label, value
    countries.put("Chinese", Locale.SIMPLIFIED_CHINESE);
}

That runs when the class is loaded, before any instances are created, and does indeed add some entries to countries. If there are multiple static initializers, they're run in source code order. See Static Initializer Blocks in this tutorial.


FWIW, there are also per-instance versions of both of those. An instance field:

private int foo;

...and an instance initializer; they look a bit weird, because they're just blocks with nothing in front of the block:

{
    this.foo = 42;
}

In context, and with a second instance member:

class Thing {
    private int bar = 16; // An initializer on the declaration
    private int foo;

    // An instance initializer block
    {
        this.foo = 42; // Or just foo = 42;, but I prefer to be clear
    }
}

So you can do the same sort of thing for instances.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
6

Basically yes, it's formally called a static initializer. And per JLS-8.7 Static Initializers

A static initializer declared in a class is executed when the class is initialized (§12.4.2). Together with any field initializers for class variables (§8.3.2), static initializers may be used to initialize the class variables of the class.

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
4

Those are called Static Initialization Blocks.

A static initialization block is a normal block of code enclosed in braces, { }, and preceded by the static keyword. Here is an example:

static {
    // whatever code is needed for initialization goes here
}

A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.

There is an alternative to static blocks — you can write a private static method:

class Whatever {
    public static varType myVar = initializeClassVariable();

    private static varType initializeClassVariable() {

        // initialization code goes here
    }
}

The advantage of private static methods is that they can be reused later if you need to reinitialize the class variable.

They are called whenever the class is first initialized, and can be used to conveniently initialize fields.

Pokechu22
  • 4,984
  • 9
  • 37
  • 62
4

The static variable countries which is declared as a Map is populated using a static initializer. There are two entries that are being added to the Map.

static{
    countries = new LinkedHashMap<String,Object>();
    countries.put("English", Locale.ENGLISH); //label, value
    countries.put("Chinese", Locale.SIMPLIFIED_CHINESE);
}

One effect of the

static initializer

is that it runs when the class is loaded and that the block is thread safe and therefore it is used in design patterns such as singletons etc. to alleviate the need for thread synchronization.

Please see this thread for details on that: Are Java static initializers thread safe?

Community
  • 1
  • 1
Khanna111
  • 3,627
  • 1
  • 23
  • 25
3

Think of it the same way you might think of an object's member fields. You might have something like this:

private final Map<String, Object> countries;

public ClassName(){
    countries = new LinkedHashMap<String,Object>();
    countries.put("English", Locale.ENGLISH); //label, value
    countries.put("Chinese", Locale.SIMPLIFIED_CHINESE);
}

This would initialize the member field each time a new ClassName() is declared to some "initial" state. The following:

static{
    countries = new LinkedHashMap<String,Object>();
    countries.put("English", Locale.ENGLISH); //label, value
    countries.put("Chinese", Locale.SIMPLIFIED_CHINESE);
}

...essentially does the same thing, except does it for static fields. Now when the class is loaded, this static block is called and initializes the static fields before they can be used so that they have some "initial" state. This is often used when you have something that will not change (for instance you may want to set up a map that makes lookup of certain things easy) or when you need to set something up that might throw an exception yet the thing you are trying to set up really should be static, such as:

private static KeyPairGenerator KPG;

static {
    try {
        KPG = KeyPairGenerator.getInstance("RSA");
        KPG.initialize(2048);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        System.err.println("Couldn't get a Key Pair Generator...exiting");
        System.exit(1);
    }
}

In the above case, I only need a single KeyPairGenerator for all of my classes (assuming I'm always going to use RSA encryption with a key size of 2048). With this single KeyPairGenerator I can generate multiple public private key pairs. However, creating the KeyPairGenerator throws a NoSuchAlgorithm exception (which cannot happen since Java is required to support RSA with a key length of 2048). So I can still get my static KeyPairGenerator by using this static initializer.

Jared
  • 940
  • 5
  • 9
0

It is used to create variable and initialize it during class loading (that's when static{} block executes).

As Java Language Specification States:

Static initializers (§8.7) are blocks of executable code that may be used to help initialize a class.

And it is indeed commonly used in small tutorial programs to initialize values.

On the other hand they also have usage in "bigger" programs. You can also use it register classes in Factory object. In this case each concrete product registers itself in the factory. By doing this you don't have to modify factory class when new concrete product is added.

class OneProduct extends Product
{
    ...
    static
    {
        ProductFactory.instance().registerProduct("ID1", new OneProduct());
    }
    public OneProduct createProduct()
    {
        return new OneProduct();
    }
    ...
}
Marcin Szymczak
  • 11,199
  • 5
  • 55
  • 63