Reputation: 72294
I personally quite like instance initializers - I use them to assign default values to things such as collections so when writing constructors I don't have to remember to assign them the same default values each time. It seems quite elegant to me - avoids annoying NPE's popping up and avoids duplicate code. A private method doesn't seem as nice because a) it can't assign values to final fields, b) it could be run elsewhere in code and c) the method still needs to be explicitly called at the start of each constructor.
However, the flip side with others I have spoken to is that they're confusing, some people reading the code might not understand what they do or when they're called and thus they could cause more problems than they solve.
Are proper use of these initializers something to be encouraged or avoided? Or is it an "each to their own" case?
Upvotes: 6
Views: 477
Reputation: 70564
It depends, for instance on the level of knowledge about Java readers of your code can be expected to have, and whether the alternatives are practical.
Alternatives are:
Since initializers are uncommon, you should only prefer them when there is a clear advantage to using them. My most recent use of one was:
private final Collator collator = Collator.getInstance();
{
collator.setStrength(Collator.SECONDARY);
}
in a class with several constructors with rather different argument lists and half a dozen other fields.
Upvotes: 4
Reputation: 23629
I would stay they are preferred. But based on the other responses it appears it might be more "to each his own". I like them because it keeps the related information together. Rather than declaring a value and setting it in the constructor, you can do it all in one place.
Upvotes: 1
Reputation: 35542
It is better to overload your constructor and have as many constructor variations as you like. The best example is Java's Arraylist. It has two constructors. One that takes a integer as an argument and other being a default constructor. If you take a look at the default constructor, it infact calls the Single argument constructor with a constant value 10.
List<Object> x = new ArrayList<Object>(); //Creates with default capacity 10
List<Object> y = new ArrayList<Object>(40); //Creates with the specified capacity 40
Upvotes: 1
Reputation: 724
I don't really use them but one case I can see them useful is when you have multiple constructors, not calling themselves (this(..)), that need some common initialization logic shared, and no need to create a specific private method for that. Oh and the only place I use instance initializers are for quickly initialize in one-line Maps for instance, eg:
Map<String,String> m = new HashMap<String,String>(){{
put("a","b");
put("c","b");
put("d","b");
}};
Could be useful to initialize a map in let's say an interface
interface A {
Map<String,String> PROPS = Collections.unmodifiableMap(new HashMap<String,String>(){{
put("a","b");
put("c","b");
put("d","b");
}});
}
Still doing so you end up with a annonymous subclass of HashMap...
Upvotes: 1
Reputation: 1347
You can use a constructor with parameters and this constructor calls the private setters. And than implement a default constructor who calls that contructor with default values. If you want assign default values to properties, do it in the declaration.
The instance and static initializers are good to init complex datastructures like matrices or cubes.
By the way, a final property is mostly called a constant.
Upvotes: 0