Java static field initialization

I just spent half an hour trying to figure it out, I managed to fix my code, but I donโ€™t quite understand what was going on, and I wondered if anyone could shed some light on it.

I have a utils class that contains several static fields (for example, the database connection endpoint) that are used by various other programs depending on the task. Essentially a library.

Here's how it looked earlier (still broken);

//DBUtils.java public final class DBUtils { private static DBConnection myDBConnection = spawnDBConnection(); private static DBIndex myDBIndex = null; private static DBConnection spawnDBConnection() { //connect to the database //assign a value to myDBIndex (by calling a method on the DBConnection object) <- IMPORTANT //myDbIndex NOT NULL HERE System.out.println("database connection completed"); //return the DBConnection object } public static searchDB(String name) { //use the myDBIndex to find a row and return it } } 

In short, I use the static spawnDBConnection () method to assign values โ€‹โ€‹to both myDBConnection and myDBIndex . This works fine, the first output line from my program is always "database connection completed", neither myDBConnection nor myDBIndex are zero at the end of the spawnDBConnection () method, everything is as it should be.

My external program looks like this:

 //DoSomethingUsefulWithTheDatabase.java public final class DoSomethingUsefulWithTheDatabase { public static void main(String args[]) { DBUtils.searchDB("John Smith"); //fails with NullPointerException on myDBIndex! } } 

This searchDB call occurs after spawnDBConnection completes, I made extensive use of standard output to show this. However, once inside the searchDB method, the value of myDBIndex is null! This is a static field, and it was not null at the end of spawnDBConnection, no other assignments were made, and now it is null :(

A simple fix was to remove "= null" so that the field declaration now looks like;

 private static DBIndex myDBIndex; 

Why did this make a difference? I am completely confused by this.

+7
source share
4 answers

This is because the null to myDBIndex is executed after

 private static DBConnection myDBConnection = spawnDBConnection(); 

eg. overrides destination in spawnDBConnection

Sequence:

  • declare fields myDBConnection , myDBIndex
  • Initialize myDBConnection = spawnDBConnection();

    What includes calling spawnDBConnection and assigning a return value to myDBConnection

  • Initialize myDBIndex (with null)

In your second example, the 3rd step does not exist.

+13
source

Why did this make a difference? I am completely confused by this.

The initializer for spawnDBConnection started, then the initializer for myDBIndex started. The initializer for myDBIndex sets to null. Since this happened after spawnDBConnection set it to a non-zero value, the end result was that it was null.

Try not to do this - it is odd for a method called by a static initializer to set other static variables.

+7
source

This is what happens in the generated static initializer block:

 static { myDBConnection = spawnDBConnection(); myDBIndex = null; } 

Hope this is clear now.

+1
source

As I know, if you define your method in front of your fields, it works, during initialization, the class is parsed from above :

 public class DbUtils { private static String spawnDBConnection() { System.out.println("database connection completed"); return "INIT"; } private static String myDBConnection = spawnDBConnection(); private static int myDBIndex = 0; public static void main(final String[] args) { System.out.println(myDBConnection); } } 

Exit:

 database connection completed INIT 
0
source

All Articles