Java statics

tags: java

Written on October 25, 2015

Java statics might be a bit mysterious for beginners. Here’s my clarification for myself :

static fields

DummyClass.java:

public class DummyClass {
	
	private static int a;

	public static int getA() { return a; }
	public static void setA(int a) { DummyClass.a = a; }
}

StaticFields.java:

public class StaticFields {
	public static void main(String[] args) {
		DummyClass d1 = new DummyClass();
		DummyClass d2 = new DummyClass();
		
		d1.setA(5); // works, bad style, as DummyClass.setA(5) would avoid confusion about the static member a
		d2.setA(6); // same as above
		
		System.out.println(d1.getA()); // will print "6" as d2.setA() sets the value of the static member
		System.out.println(d2.getA());
	}
}

clarification: DummyClass is instantiated as d1 and d2. d1 sets the static member a to 5 and afterwards d2 sets a to 6. As “static” qualifier mark the fields as fields of the classes and not of the instances, the d2 call of setA will overwrite the “5” that was set before by the d1 call.

static methods

DummyClass.java:

public class DummyClass {
	
	public static void sayHello(){
		System.out.println("hello");
	}
	
	public void sayBye(){
		System.out.println("bye");
	}	
}

StaticMethods.java:

public class StaticMethods {

	public static void main(String[] args) {
		DummyClass.sayHello(); // can be called without availability of a DummyClass instance
		// DummyClass.sayBye(); // cannot be called because calling non static methods requires present instance
		DummyClass d = new DummyClass();
		d.sayBye();	// now it will work
		d.sayHello(); // possible but bad style because it confuses as their is only one DummyClass.sayHello()
	}
}

clarification: non static method sayBye() can only be called from an instance of DummyClass where static methods can be called before construction of a DummyClass instance. This works only because sayHello() is a method of the class itself and initiated while classloading before (!) cass construction.

static initializers

DummyClass.java:

public class DummyClass {
	
	private static List<Integer> valueList;
	
	static { 
		// static initializer: It's executed when the class is loaded. good place to put initialization of static variables.
		// block of code which is executed when the class gets loaded by a classloader.
		// There is an alternative to static blocks — you can write a private static method:
		System.out.println("this is the static initializer");
		
		valueList = new ArrayList<Integer>();
		valueList.add(23);
		valueList.add(42);
		valueList.add(33);
	}
}

StaticInitializers.java:

public class StaticInitializers {
	public static void main(String[] args) {		
		System.out.println(DummyClass.getValueList());
	}
}

clarification: static blocks can be used for initializing static members e.g. for data creation. As it is a static block, it will be executed within classloading and there is no need for an instantiation of DummyClass.

constructor blocks

DummyClass.java:

public class DummyClass {
	
	{
		// block of code which is executed when the class gets loaded by a classloader.
		// this constructor block "injects" common functionality into all constructors
		// also called initializer block
		System.out.print("injected stuff ::: ");
	}
	
	public DummyClass(String string){
		System.out.println(string);
	}
	
	public DummyClass(int a){
		System.out.println(a);
	}
	
	public DummyClass(boolean bool){
		System.out.println(bool);
	}
}

ConstructorBlocks.java:

public class ConstructorBlocks {
	
	public static void main(String[] args) {

		// will print "injected stuff ::: skywalker"
		DummyClass d1 = new DummyClass("skywalker");
		
		// will print "injected stuff ::: 42"
		DummyClass d2 = new DummyClass(42);
		
		// injected stuff ::: true
		DummyClass d3 = new DummyClass(true);
	}
}

clarification: in contrast to static initializers, code blocks without that static qualifier can be seen as “constructor enricher”. That means, that every constructor of that class gets injected with extra statements. This might be helpful in scenarios where different constructors share a common set of calls before they are executed.