Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are instance initializers considered bad style?

Tags:

java

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?

like image 234
Michael Berry Avatar asked Jan 13 '11 00:01

Michael Berry


2 Answers

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:

  • inline into every constructor. If there are several constructors, this violates DRY.
  • have all constructor delegate to the same constructor, and put the code in that one. If the constructors are non-trivial, and take different arguments, this might require to write a new constructor that receives the values of all fields in its arguments. If there are many fields, this can get rather lengthy (and hard to read, since it is not obvious which value is being assigned to which field)
  • have all constructors invoke an init method. Can't assign final fields that way. Should probably prevent the method from being overridden. Might want to prevent it from being called several times.

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.

like image 59
meriton Avatar answered Sep 28 '22 01:09

meriton


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...

like image 33
CodegistCRest Avatar answered Sep 28 '22 00:09

CodegistCRest