Dataslope logoDataslope

Constructors and State

Bringing objects into existence in a valid state, overloaded constructors, and the role of `final` and immutability

A constructor's job is small but absolute: make sure that an object exists in a valid state from the moment it is born. A class that fails at this lets the rest of the system inherit half-built objects — and half-built objects produce bugs that look like ghosts.

What a constructor is

A constructor looks like a method but with two differences:

  1. It has the same name as the class.
  2. It has no return type.

When you write new Person("Ada", 30), Java allocates a new Person on the heap and then calls the constructor on that fresh allocation to initialize it.

Code Block
Java 8 (Update 492)

The default constructor and what happens without one

If a class declares no constructors at all, Java secretly gives it a no-argument constructor that does nothing. The moment you declare any constructor, that freebie disappears.

Code Block
Java 8 (Update 492)

Constructors enforce invariants from the very first moment

The thing constructors really do for design is enforce invariants before the object is allowed to exist. The rule "a Person's age is never negative" is a class rule — and the class can enforce it by refusing to be constructed in violation of it.

Code Block
Java 8 (Update 492)

This is enormously important. Once that constructor returns successfully, every other method in Person can assume the name is non-blank and the age is ≥ 0. Without that guarantee, every method would need to start with defensive checks.

Overloaded constructors and this(...)

Java lets a class have several constructors with different parameter lists. This is called constructor overloading. The most common use is convenience: one "real" constructor that does the work, and a shorter one that fills in defaults by calling the real one with this(...).

Code Block
Java 8 (Update 492)

The rule for this(...) chains: if you use it, it must be the first statement in the constructor. This guarantees there is exactly one "primary" constructor that does the actual initialization, and all others funnel through it.

final fields and immutability

When a field is declared final, it must be assigned exactly once, in the constructor (or at the declaration). After that it cannot be reassigned.

An object whose fields are all final and whose constructor sets them is immutable: it cannot change after creation. Immutable objects are extremely safe — they can be passed around freely, shared between methods, even shared between threads, with no risk of accidental mutation.

Code Block
Java 8 (Update 492)

That add method is a small pattern worth remembering: operations return new instances instead of mutating the receiver. price stays $19.99 forever; taxed is a new Money. This is how strings, BigDecimal, LocalDate, and many other Java built-ins work.

Multi-file practice: build a valid object

Challenge
Java 8 (Update 492)
Valid User construction

Implement User so it cannot be constructed in an invalid state.

Rules:

  • username must be non-null and length >= 3. Otherwise throw IllegalArgumentException("invalid username").
  • email must contain the character '@'. Otherwise throw IllegalArgumentException("invalid email").
  • Both fields are private final.
  • Add public methods username() and email() that return the values.

Main runs three scenarios and is expected to print:

ok: ada @ ada@oop.dev
bad: invalid username
bad: invalid email

Test your understanding

QuestionSelect one

What is the single most important job of a constructor?

To call all the other methods in the class

To bring an object into existence in a valid state, enforcing its invariants

To print a debug message describing the new object

To allocate memory for the object

QuestionSelect one

If a class declares the constructor public Person(String name, int age) and no no-argument constructor, what happens when you write new Person()?

It runs Java's default no-arg constructor

It runs the two-argument constructor with null and 0

It fails to compile — there is no matching constructor

It produces a NullPointerException at runtime

QuestionSelect one

Why is it useful for a class like Money to be immutable (all fields final, operations like add return new instances)?

Immutable objects are slightly larger in memory and that helps caching

The JVM can compile them down to machine code more easily

They cannot accidentally change underneath you, so they can be passed and shared freely without surprising mutations

They automatically run faster than mutable objects

On this page