using instance initializer to deal with constructor overloading

A pattern I sometimes see is that a constructor might take either no argument or one argument. Now, I wonder whether the ‘better’ approach is to move common code to the most defined constructor – or to use the instance initializer in this case. For example, one way of always generating an ID for every class created:

 public SomeClass(){
     this("Hello");
 }

 public SomeClass(String s){
     this.s = s;
     this.id = generateId();
 }

versus writing it like this:

 {
     this.id = generateId(); // method does not depend on the class
 }

 public SomeClass(){
      this("Hello");
 }

 public SomeClass(String s){
      this.s = s;
 }

The reason for using the Instance Initializer would be because I want to always run the method when the class is created, and in the future someone else might change the class’s constructors and forget to do this. Whilst it is less likely to remove the instance initializer (without realizing what you are doing).

But on the other hand, I am not sure how about readability in this case.

The examples are a bit contrived, not real-world examples.

The reason for using the Instance Initializer would be because I want
to always run the method when the class is created, and in the future
someone else might change the class’s constructors and forget to do
this. Whilst it is less likely to remove the intance initializer
(without realising what you are doing).

Doing the one (using the Instance Initializer) or the other one (constructor) should not be used as trick to avoid coding error when the class is modified.
And anyway, why Initializer would give better insurance about it ?

You want to ensure that the constructor do what it designed to do ?
Writing an unit test that validates this behavior and that is automatically executed at each build.
That’s all.

I have never seen a use of instnace initializer in real life. (I actually did see it and played with it for a bit in one of theoretical questions on this site). In real life though you often can see a static initializer block:

public class Bla {
  static {
     //do something
  }
  ....
}

As for common code what could be done is to have a method called init() that is called by all constructors. In your example it would look like

 public SomeClass(){
      this("Hello");
 }

 public SomeClass(String s){
      init();
      this.s = s;
 }

  private init()  {
     this.id = generateId(); // method does not depend on the class
 }

I think the reasonable solution here:

 private final Whatever id = generateId();

In other words:

  • make sure the compiler knows that this should be initialized (so use final)
  • and instead of using an init block (rather uncommon) simply do initialize once, “in place”