W3docs

Java Constructors

Use constructors to initialize Java objects — default, parameterized, and overloaded constructors, plus constructor chaining.

A constructor is a special method that runs once when an object is created. Its job is to take the new instance from "every field at its default value" to "ready to use." Up to now you've been setting fields one by one after new Dog(); a constructor lets you bundle that work into the new call.

Anatomy of a constructor

A constructor looks like a method, with three differences: it has the same name as the class, no return type (not even void), and it's called only by new:

public class Point {
  int x, y;

  public Point(int x, int y) {       // constructor
    this.x = x;
    this.y = y;
  }
}

Point p = new Point(3, 4);           // runs the constructor

The argument list goes inside the () after the class name in the new expression. Java matches that argument list to a constructor on the class, just like it matches a method call to a method.

The default constructor

If you don't declare any constructor, Java gives the class a default constructor — a no-arg constructor that does nothing:

public class Empty { }    // compiler generates a no-arg constructor

Empty e = new Empty();    // works

This is how new Dog() worked in the earlier examples even though we never wrote public Dog() { ... }. The moment you declare any constructor of your own, the free default goes away:

public class Point {
  int x, y;
  public Point(int x, int y) { this.x = x; this.y = y; }
}

Point p = new Point();    // ERROR — no no-arg constructor exists

If you want both, declare both — see overloading below.

Why use a constructor?

Two reasons.

1. Required fields. A constructor lets you make some fields non-optional. With public-field-then-assign, there's nothing stopping a caller from creating a Person with no name. With a Person(String name) constructor, you can't.

2. Invariants. A constructor can validate its arguments before the object exists in a usable form. If a Circle requires a positive radius, the constructor can throw on a negative one — the broken object is never created at all.

public class Circle {
  double radius;
  public Circle(double radius) {
    if (radius <= 0) throw new IllegalArgumentException("radius must be > 0");
    this.radius = radius;
  }
}

The caller now cannot get a Circle with a non-positive radius.

Overloaded constructors

A class can have multiple constructors with different parameter lists, exactly like overloaded methods:

public class Rectangle {
  double width, height;

  public Rectangle()                      { this(1, 1); }
  public Rectangle(double side)           { this(side, side); }    // a square
  public Rectangle(double w, double h)    { this.width = w; this.height = h; }
}

Now all three of these compile:

Rectangle a = new Rectangle();          // 1 x 1
Rectangle b = new Rectangle(5);         // 5 x 5
Rectangle c = new Rectangle(3, 4);      // 3 x 4

this(...) — constructor chaining

Inside one constructor, this(args) calls another constructor on the same class. That's how the Rectangle example above avoided duplicating field-assignment code: the two convenience constructors delegate to the full one.

Two rules:

  • this(...) must be the first statement in the constructor body.
  • A constructor can chain to one other constructor.
public Rectangle()           { this(1, 1); }      // ok
public Rectangle(double s)   { System.out.println("hi"); this(s, s); }   // ERROR

The reason for the "first statement" rule is that the JVM has to fully initialize the object exactly once before any other code runs.

super(...) — calling the parent

When a class extends another, every constructor either explicitly calls a parent constructor with super(args), or implicitly calls the parent's no-arg constructor. We'll cover this fully in the inheritance and super keyword chapters; for now, just know that super(...) exists and has the same first-statement rule as this(...).

Constructors cannot return a value

A constructor has no return type — not even void. If you write one:

public void Point(int x, int y) { ... }    // not a constructor!

…it's a regular method that happens to be named Point. The compiler won't warn you; new Point(3, 4) will then fail to compile because the real constructor it's looking for doesn't exist. This is a surprisingly common typo.

Initialization order

For a single class, the order is:

  1. Field default values are assigned (e.g. int fields become 0).
  2. Inline field initializers (int count = 5;) and any instance initializer blocks run in the order they appear.
  3. The constructor body runs.
public class Demo {
  int a = compute("a-init", 1);
  int b;

  { b = compute("b-block", 2); }    // instance initializer

  public Demo() {
    System.out.println("constructor; a=" + a + ", b=" + b);
  }

  static int compute(String label, int v) {
    System.out.println(label);
    return v;
  }
}

new Demo() prints a-init, b-block, then constructor; a=1, b=2.

In practice, almost all initialization belongs in the constructor body. Instance initializer blocks are rare in real code; they exist mainly for situations like anonymous classes (covered later).

A worked example

java— editable, runs on the server

What's next

Inside constructors you've already seen this.field = field to disambiguate a parameter from a field. The this keyword chapter pins down what this is and the handful of places you need to write it explicitly.

Practice

Practice

A class declares only one constructor, public Point(int x, int y). Which call fails?