In the previous article, we’ve seen that constructors are the most important members of a class. That conclusion tells us that we must pay special attention to implementing the constructor (or constructors) properly. In this blog post, we’ll formulate the first of several constructor rules I believe every class must obey.

A class without a constructor

For sure you’ve seen a class without a constructor. It looks like this:

1public final class Player {
2    private final String name;
3    private final int birthYear;
4    private final double experience;
5
6    //methods go here
7}

To me, such classes are a really sad sight. Yes, I know that technically even such classes have a constructor. Even if you don’t write one, Java will generate a public, no-arg constructor for you. It will even initialize all the fields—objects to null, primitives to 0. Yes, I also know it’s quite convenient not to write “unnecessary” constructors. But please think more deeply about it. Even if you think that default field initialization is good enough for your application, do you really want to let the language initialize your objects? Don’t you want to prevent the creation of invalid objects in your app? Remember that after creating all the necessary objects, we will start our application, and every bit of sloppiness or shortcut we took while creating and wiring our objects will almost certainly appear at execution time.

What should the (only) constructor do

Even though classes can have multiple constructors, here we’ll focus only on adding just one constructor to the class. Such a constructor has the following responsibilities:

  • to disallow construction of invalid objects
  • to initialize all the fields

Disallowing construction of invalid objects is typically done via parameter validation. In an enterprise application, you might use Bean Validation to that end. For this article, I’ll simply use plain Java. Typically, you should throw an exception if someone passes a parameter that would cause the creation of an invalid object:

 1public final class Player {
 2    //fields go here
 3
 4    public Player(String name, int birthYear, double experience) {
 5        if (name == null) {
 6            throw new IllegalArgumentException("name cannot be null");
 7        }
 8        if (birthYear < 1900) {
 9            throw new IllegalArgumentException("birthYear must be >= 1900");
10        }
11        //further validation
12    }
13}

You should adjust validation messages and exceptions to match personal preference or to be in line with already existing validation in the application you’re developing.

If the validation succeeds, initializing all the fields should be dead simple. Assign parameters to the fields (eventually creating defensive copies if needed to make objects immutable), and you’re done!

 1public final class Player {
 2    //fields go here
 3
 4    public Player(String name, int birthYear, double experience) {
 5        //validation goes here
 6        this.name = name;
 7        this.birthYear = birthYear;
 8        this.experience = experience;
 9    }
10}

After both validation and initialization, your constructor is ready to create perfectly valid and usable objects.

Takeaways and action points

  • A class must have a constructor
  • It must disallow construction of invalid objects and initialize all the fields
  • Go through the code base, find classes without a constructor, and implement a proper one!

Dear fellow developer, thank you for reading this article about a rule that classes must have at least one constructor. Until next time, TheJavaGuy salutes you 👋!