Skip to content
Java core 3 min read

Constructors

A constructor is a special block that runs when an object is created with new. Its job is to bring an object into a fully valid initial state. A constructor shares the class’s name, declares no return type (not even void), and may be overloaded to support different ways of building the same type.

Default vs Parameterized Constructors

If you write no constructor at all, the compiler synthesizes a default constructor: a public, no-argument constructor that simply calls super().

public class User {
    String name;
}
// Compiler provides: public User() { super(); }

A parameterized constructor accepts arguments to initialize fields explicitly.

public class User {
    private final String name;
    private final String email;

    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }
}

Warning: The moment you declare any constructor, the compiler stops generating the default one. If you still need a no-arg constructor, you must write it yourself.

The No-Arg Constructor Rule

Frameworks like Jackson, JPA, and many DI containers instantiate objects reflectively and often require a no-argument constructor. If your class has only parameterized constructors, add an explicit no-arg one to stay compatible.

public User() {
    this("anonymous", "none@example.com"); // delegate via this()
}

Constructor Overloading

You may declare multiple constructors that differ in parameter list. The compiler selects the right one based on the arguments supplied at the call site.

public class Rectangle {
    private final int width, height;

    public Rectangle(int side)            { this(side, side); }
    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }
}

this() Chaining

this(...) calls another constructor in the same class, centralizing initialization logic so it lives in one place. When present, it must be the first statement in the constructor.

public class Server {
    private final String host;
    private final int port;

    public Server()              { this("localhost"); }
    public Server(String host)   { this(host, 8080); }
    public Server(String host, int port) {
        this.host = host;
        this.port = port;
    }
}
System.out.println(new Server().port);

Output:

8080

super() and the Superclass

super(...) invokes a constructor of the parent class and, like this(), must be the first statement. If you write neither this() nor super(), the compiler inserts an implicit super() call to the parent’s no-arg constructor.

public class Animal {
    Animal(String name) { /* ... */ }
}

public class Dog extends Animal {
    Dog() {
        super("dog"); // required: Animal has no no-arg constructor
    }
}

Note: A constructor cannot use both this() and super()—each can be the first statement, but only one can occupy that slot. Chains of this() eventually bottom out in a constructor that (implicitly or explicitly) calls super().

Copy Constructors

Java has no built-in copy constructor, but you can write one to create a new object from an existing instance. This is a clean, explicit alternative to Cloneable/clone().

public class Point {
    private final int x, y;

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

    // Copy constructor
    public Point(Point other) {
        this(other.x, other.y);
    }
}

Tip: For deep copies, copy mutable reference fields rather than aliasing them, so the original and the copy stay independent.

Best Practices

  • Validate arguments in the constructor; reject invalid state early with IllegalArgumentException.
  • Centralize logic with this() chaining instead of duplicating field assignments.
  • Keep constructors cheap—no blocking I/O or heavy work; favor factory methods for that.
  • Make fields final and assign them once in the constructor for safe immutability.
  • Add an explicit no-arg constructor when a framework requires it.
  • Prefer static factory methods or the Builder pattern when a class has many optional parameters.
Last updated June 1, 2026
Was this helpful?