Problem
Suppose, I have a data access layer class, where I want to specify database connection parameters. Usually, I do it as static variables and initialize it right after definition, e.g. see DB_NAME
variable case.
Performing code review, I paid attention that sometimes such logic is implemented with a static block, e.g. see DB_HOST
variable case.
public class DAL {
private static final String DB_NAME = "MY_DB";
private static final String DB_USER = "DB_ADMIN";
private static final String DB_HOST;
static {
DB_HOST = "127.0.0.1";
}
}
The questions:
- Is there any benefit from using a static block in such specific scenario?
- When should I prefer to use a static block over a regular static variable initialization?
P.S. I found a similar question on SO: Why use static blocks over initializing instance variables directly?, but if you have something to add, you’re welcome.
Solution
- In such scenario it only obstructs code readability. No benefits.
- You should use static block only if static field initialization is not enough (e.g. you should call several methods, or this methods throw checked exceptions).
Just created 2 sample classes:
public class Static {
public static String s = "qwe";
}
public class StaticBlock {
public static String s;
static {
s = "qwe";
}
}
And using javap -c
we can see bytecodes of this classes:
Compiled from "Static.java"
public class Static {
public static java.lang.String s;
public Static();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
static {};
Code:
0: ldc #2 // String qwe
2: putstatic #3 // Field s:Ljava/lang/String;
5: return
}
Compiled from "StaticBlock.java"
public class StaticBlock {
public static java.lang.String s;
public StaticBlock();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
static {};
Code:
0: ldc #2 // String qwe
2: putstatic #3 // Field s:Ljava/lang/String;
5: return
}
As you can see, bytecodes are identical 🙂
UPD: Its getting more interesting! If we add final
modifier to our static field, bytecodes will be different.
public class Static {
public static final String s = "qwe";
}
public class StaticBlock {
public static final String s;
static {
s = "qwe";
}
}
We will have:
Compiled from "Static.java"
public class Static {
public static final java.lang.String s;
public Static();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
}
Compiled from "StaticBlock.java"
public class StaticBlock {
public static final java.lang.String s;
public StaticBlock();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
static {};
Code:
0: ldc #2 // String qwe
2: putstatic #3 // Field s:Ljava/lang/String;
5: return
}
I found a little bit of explanation in this question.