Effective Java — Item 2 — I

Kasumi Gunasekara
4 min readApr 30, 2019

--

Consider a builder when faced with many constructor parameters

Photo by Sarah Pflug from Burst

Recently, I have been reading Effective Java by Joshua Bloch which provides a definitive guide to best practices of Java Language. The book has been arranged with “Items” throughout the chapters with a common numbering pattern. This story is about the Item 2 which comes under Chapter 2: Creating and Destroying Objects.

“Consider a builder when faced with many constructor parameters”

There can be situations where the constructor has multiple parameters. For an instance, consider the class that represents nutrition facts on packaged food. It contains many nutrition facts including calories, fat, Sodium, carbohydrate, protein, Fiber, Calcium. In addition, there can be few required fields and many additional fields since certain number of nutrition facts are optional for a particular food product.

The programmers have followed several approaches in such scenarios as follows:

Telescoping Constructor Pattern

This is a traditional approach from programmers which introduces multiple constructors to the class:

  • A constructor with only required parameters
  • A constructor with all required parameters and one optional parameter
  • A constructor with all required parameters and two optional parameters
  • ….
  • A constructor with all required parameters and all optional parameters

Let us consider another scenario about details of food provided by a company where their netWeight, packType and servingSize are required. Those products include regular jams, canned fruits, canned vegetables. In this instance, only three optional nutrition facts are used, but in the actual situation, there can be many parameters.

FoodFacts Class with Telescoping Constructor Pattern

Creating an instance — Choose the constructor with shortest parameter list and includes all parameters that you want to provide. Even-though the shortest one is chosen, you might need to give values to other parameters that are not needed to provide.

When there are many parameters, it could become hard to manage constructors. It is difficult to write a focused, simple, and intention-revealing code that is readable because of the way of handling large number of parameters in this approach. The reader has to read carefully to understand the parameter values given.

JavaBeans Pattern

In this approach, a constructor with zero parameters is used to create the objects, and then the field values are given using setter methods for each parameter.

FoodFactBean Class for JavaBeans Pattern

Although this approach is a descriptive one, and readable, its construction has been achieved via multiple calls. This can be a drawback if an attempt occurs to use the object while it is in an inconsistent state.

What is inconsistent state ?— The object inconsistent state while it is still being setting up or modifying a value of a particular field after the object has already been constructed.

When an object is used in this invalid state that is when all the values to be set are not completed yet, then certain values would not be there for the usage. The bugs which are caused due to them are hard to find and debug.

“JavaBeans pattern precludes the possibility of making a class immutable”

Therefore, programmer needs to put much effort on ensuring thread safety and handling concurrency in this approach. Otherwise, an immutable class which is suitable for caching purposes is inherently thread-safe.

It is better to have a proper validation of the construction completion to minimize the cons of JavaBeans pattern. That means to disable the use of an object (freeze the object) until its construction is done. According to Effective Java, it is rarely applied since it can cause errors at run-time because programmer may or may not have call this disabling method on an object before its usage.

Builder Pattern

This approach has the safety of Telescoping Pattern and the readability of JavaBeans. A static member class called Builder of class it builds (i.e FoodFactsBuilder) is used to create the object and to return it:

  • The outer class (FoodFactsBuilder) has a private constructor with Builder as the single parameter
  • Create Builder object with a constructor with all required fields or a static factory method
  • Set optional parameters as preferred using setter-like methods which return the builder itself on Builder object
  • Call build() method with no parameters to generate the object (Typically, this is immutable)
FoodFactBuilder Class for Builder Pattern

The setter-like methods of Builder return the builder object , therefore they can be chained (Method Chaining) i.e. a fluent API which improves the readability of the code.

FoodFactBuilder pineappleJam = new FoodFactBuilder
.Builder(240,8, "Bottle")
.calories(8)
.sodium(7)
.build();

“Builder pattern simulates the named optional parameters found in Python and Scala”

The named optional parameters are optional fields passed to a function in Python. The Builder pattern in Java, implements this feature using setter-like methods which is a different approach than Python:

Named Optional Parameter Implementation in Python

Here in Python, food_fact is the Python class for the purpose, and optional arguments of the food_fact_builder() function has default values (calories, sodium, carbohydrate).

Validation of Parameters — This can be achieved by checking the validity of required fields in the builder’s constructor, and optional fields in their setter-like methods.

Effective Java — Item 2 — II narrates about the “Builder pattern is well-suited for class hierarchies”.

I hope this article has been useful for you. If I missed anything, please let me know.

Happy Coding!!!

--

--