Reputation: 137
I was doing some reading on Java classes, and I came upon static initializers. However, I can't see the point of using them when you can just set default values in the first place. For example,
static int a;
static {
a = 5;
}
versus
static int a = 5
in a class definition.
Is there a difference between these two? If not, when would you use static initializers versus default values?
Upvotes: 3
Views: 329
Reputation: 3853
There is no difference. In fact, the compiler changes the short form into a declaration-plus-static-block for you. If you run "javap" on the resulting classes they are identical.
The "javap" tool that comes in the JDK with the compiler is a great way to look at the code and know exactly "what is the difference"!
public class Test {
//static int a= 5;
static int a;
static {
a = 5;
}
}
javap -c Test.class
Compiled from "Test.java"
public class Test {
static int a;
static {};
Code:
0: iconst_5
1: putstatic #10 // Field a:I
4: return
public Test();
Code:
0: aload_0
1: invokespecial #15 // Method java/lang/Object."<init>":()V
4: return
}
Upvotes: 1
Reputation: 837
Is there a difference between these two?
No, In this case there is no difference as in your static initializer block you are just assigning a value to a variable.But in some very complex scenarios this may not be the case.
If not, when would you use static initializers versus default values?
This works well when the initialization value is available and the initialization can be put on one line. However, this form of initialization has limitations because of its simplicity. If initialization requires some logic (for example, error handling or a for loop to fill a complex array), simple assignment is inadequate.
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.
Upvotes: 1
Reputation: 9914
Is there a difference between these two?
No, in this case the code that you shared
If not, when would you use static initializers versus default values?
There are many scenarios, you need static initializers like , in case your application needs only one instance of an object. You can use static block in which you can implement the logic for how to get the single instance.
Upvotes: 0
Reputation: 11867
If memory serves, there's no effective difference. However, a static block can be helpful for readability purposes, or for doing tasks which take multiple steps. Take this (bad) example from my freshman year of college:
// Pattern of initial memory values, used during critter file parsing
private static Pattern memoryMatcher;
private static Pattern sugarMatcher;
private static Pattern generalMemoryMatcher;
// Block to create memoryMatcher
static {
final StringBuilder builder = new StringBuilder();
// Append each of the sugar values, separated by a pipe
builder.append("(?i)(");
for (final Sugar sugar : Sugar.values()) {
builder.append(sugar.toString());
builder.append("|");
}
// Replace final pipe with close parenthesis and create sugarMatcher
sugarMatcher = Pattern.compile(builder.replace(
builder.length() - 1, builder.length(), ")").toString());
// Append some stuff to catch ": <number>" and whitespace, then
// create memoryMatcher
memoryMatcher = Pattern.compile(builder.insert(4, "(")
.insert(builder.length() - 1, "|mem\\[-?\\d+\\]")
.append(":\\s*-?\\d*|\\s*)").toString());
// Should match mem[<number>]
generalMemoryMatcher = Pattern.compile("mem\\[-?\\d+\\]");
}
Prior to Java 8, the code that involves the for
loop I don't believe would be able to work as part of a single assignment. While Java 8's streams would let me do this as part of an assignment, the work for memoryMatcher
and sugarMatcher
would replicate some work, which isn't really desirable.
Upvotes: 1
Reputation: 310860
Is there a difference between these two?
Not in the example you posted. However the static {}
form can include arbitrary code including loops, try/catch, etc.
If not, when would you use static initializers versus default values?
When you need the extra features.
Upvotes: 2
Reputation: 262474
No difference.
when would you use static initializers versus default values?
When the code to evaluate the expression is more complex, especially if exceptions are involved.
static int a ;
static {
String x = System.getProperty("abc");
try{
a = Integer.parseInt(x);
}
catch (Exception e){
throw new IllegalArgumentException
("missing or invalid system property 'abc': "+x);
}
}
But then it is probably best practice to move the code into a private static method.
final static int a = complexCalculation();
Upvotes: 4