Never break the chain!

Each day, when we are working with code we are creating new objects. There are many ways of creation and the most used is a class constructor. But, do we initialize our object properly in the best possible way?

Let’s consider that we are owning a company which produces headphones. We want to model our domain and processes in code. In most cases our headphones are black and cost 150 dollars so we just write a class and provide default constructor:

public class Headphones {

    private final Color color;
    private final BigDecimal priceInDollars;

    public Headphones() {
        this.color = Color.BLACK;
        this.priceInDollars = BigDecimal.valueOf(150.0);
    }
  
  //other methods
  
}

Great success – our company can make plenty of 150 dollars black headphones. After some time we decide that it is time to create headphones in different colors. We can still create only black headphones and send them to a painter, but it is not efficient to cover black headphones with another color. But we don’t want to do that, as it will cost additional money.
We are mainly creating black headphones, but for this special case, we will create new constructor – we leave setting the price to a default value, but color will be provided:

public Headphones(final Color color) {
  this.color = color;
  this.priceInDollars = BigDecimal.valueOf(150.0);
}

Again, after some time, we decide that different color headphones can have a different price. And again we are creating a new constructor. Our class looks like this now:

public class Headphones {

    private final Color color;
    private final BigDecimal priceInDollars;

    public Headphones() {
        this.color = Color.BLACK;
        this.priceInDollars = BigDecimal.valueOf(150.0);
    }

    public Headphones(final Color color) {
        this.color = color;
        this.priceInDollars = BigDecimal.valueOf(150.0);
    }

    public Headphones(final Color color, final BigDecimal priceInDollars) {
        this.color = color;
        this.priceInDollars = priceInDollars;
    }
    
  //other methods
    
}

As we can see it leads us to code duplication. Each constructor has to set all fields by themselves and if we want to change the default value we have to track all constructors. What can we do with that? The first solution which came to mind is that we can inline our fields with default values:

public class Headphones {

    private Color color = Color.BLACK;
    private BigDecimal priceInDollars = BigDecimal.valueOf(150.0);

    public Headphones() {
    }

    public Headphones(final Color color) {
        this.color = color;
    }

    public Headphones(final Color color, final BigDecimal priceInDollars) {
        this.color = color;
        this.priceInDollars = priceInDollars;
    }
  
  //other methods
  
}

Now our constructors are setting only fields they want to change. We can also do it in another way and set default values using initializer:

public class Headphones {

    private Color color;
    private BigDecimal priceInDollars;

    {
        this.color = Color.BLACK;
        this.priceInDollars = BigDecimal.valueOf(150.0);
    }

  //other
  
}

These three ways of setting object fields in a moment of construction can be of course mixed – you can set one field by a constructor, the second field by inlining a value and third field set in an initializer, but what are benefits of that?

I don’t see any.

What I notice there is a plenty of problems:

– we don’t have one single point of creation – if we want to provide some behavior which all our constructor will share we will copy-paste it from one to another
– we are making our class more complicated than it should be. When we are checking class constructor we don’t want to jump between too many places to check how an object is created
– after transformation, our fields cannot be final – we are setting default values regardless of whether we change them or not, so we have to make the possibility of changing it
– unnecessary field initialization which is creating an unused object – not really a problem, until you are creating millions of objects

Big question is – what can we do to get rid of these problems?

The answer for that is a concept which is called constructor chaining.

Constructor chaining means that we are writing our constructors in a way that they are calling other constructors inside a class, finally reaching single top constructor. This top constructor is called primary, and all others are called secondary.
The primary constructor will be our single point of creation and initialization, so we can put all common behavior into it. To keep consistency we have to have only one primary constructor, ideally which will set all our class fields. Also, remember that the primary constructor doesn’t have to be public if we don’t want to expose primary constructor outside our class or package.

Constructor chaining is removing all the problems I mentioned. With that, you don’t need to worry about code duplication. In result, it will make your class less complicated and more maintainable.

– all constructors are in the end calling the primary constructor, which is a single point of creation and can share common code
– you have to check constructors only to see all initialization code, you don’t need to search the whole class
– your final fields can be final
– you don’t create unnecessary objects

I recommend you to write primary constructor as the last constructor in a class and all secondaries before, as I did in Headphones class:

public class Headphones {

    private final Color color;
    private final BigDecimal priceInDollars;

    public Headphones() {
        this(Color.BLACK);
    }

    public Headphones(final Color color) {
        this(color, BigDecimal.valueOf(150.0));
    }

    public Headphones(final Color color, final BigDecimal priceInDollars) {
        this.color = color;
        this.priceInDollars = priceInDollars;
    }

  //other methods
  
}

Never use initializer blocks.
Never initialize fields inline.
Always chain your constructors.

When you are creating a new class always think how to design it properly. Exposing many constructors will provide different ways of creation which lead to increase of the usability.

Designing a class means not only providing a nice API which will be easy to use but also means keeping all code inside maintainable and readable for developers which will work with that class in the future. Using constructor chaining with primary and secondary constructors will help in that case.

  • DrRob

    What if you need lots more parameters, all with defaults? The number of combinations quickly rises. Is there a way to use the builder pattern without losing final fields?

    • Mateusz Winnicki

      If we are talking about real objects and have a problem with a lot of parameters, at first we should check how many responsibilities it has. More than 3-4 parameters quickly indicate us that we probably should break down it to few smaller objects.
      But if we are talking about data structures like DTO or Entity mapping which have many fields with get/set we can use static nested builder. It will help to build our objects and we can put there default parameters logic. And more – we can allow bulding object only using Builder and make constructor of our basic class private. Unfortunately builder will not use constructor chaining, as by definition it will expose setters to all fields, but in this case it should be ok.