Constructors in Java: Complete Guide
A constructor is a special method called when an object is created with new. Its job is to initialize the object's fields into a valid state before any other code touches it.
Basic constructor
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
}
User u = new User("Alice", 30);
Key rules
- The name must match the class name, exactly.
- No return type β not even
void. - Cannot be
static,final, orabstract. - Can have any access modifier:
public,protected, package-private, orprivate.
The default constructor
If you don't declare any constructor, Java generates an implicit no-argument constructor. The moment you declare one, that freebie disappears.
public class Point {
int x, y;
// No constructor written β default public Point() is generated
}
Point p = new Point(); // works
// --- but ---
public class Point2 {
int x, y;
public Point2(int x, int y) { this.x = x; this.y = y; }
// No default constructor anymore
}
Point2 p = new Point2(); // β compile error
Point2 p2 = new Point2(1, 2); // β
Multiple constructors (overloading)
public class Rectangle {
private final int width, height;
public Rectangle() {
this(1, 1); // delegate to another constructor
}
public Rectangle(int side) {
this(side, side); // square
}
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
}
this(...) delegates to another constructor of the same class β and must be the first statement in the constructor body.
Calling the parent constructor
super(...) invokes a constructor of the superclass. If you don't call it explicitly, Java inserts an implicit super(). Like this(), it must be the first line.
public class Animal {
protected final String name;
public Animal(String name) { this.name = name; }
}
public class Dog extends Animal {
private final String breed;
public Dog(String name, String breed) {
super(name); // call Animal(String)
this.breed = breed;
}
}
Copy constructor
Java doesn't have a built-in copy constructor like C++, but you can write one explicitly:
public class Point {
int x, y;
public Point(Point other) {
this(other.x, other.y);
}
public Point(int x, int y) { this.x = x; this.y = y; }
}
Point a = new Point(3, 4);
Point b = new Point(a); // copy
For mutable objects, remember to copy nested collections defensively.
Private constructor
A private constructor prevents instantiation from outside the class β useful for:
- Utility classes with only static methods (e.g.
java.util.Collections) - Singletons
- Factory patterns where only a named static method exposes construction
public final class Utils {
private Utils() {
throw new UnsupportedOperationException("No instances");
}
public static int sq(int n) { return n * n; }
}
Static factory methods
A named static method is often clearer than a constructor. It can cache instances, return a subtype, or fail with a meaningful method name.
public class Color {
private final int r, g, b;
private Color(int r, int g, int b) { this.r = r; this.g = g; this.b = b; }
public static Color ofRgb(int r, int g, int b) {
return new Color(r, g, b);
}
public static Color fromHex(String hex) {
int v = Integer.parseInt(hex.substring(1), 16);
return new Color((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF);
}
}
Color c = Color.fromHex("#FF8800");
Records: constructors for free
Since Java 16, a record auto-generates a constructor matching its components:
public record Point(int x, int y) { }
Point p = new Point(3, 4);
int x = p.x(); // accessor auto-generated too
You can add a compact constructor for validation:
public record User(String name, int age) {
public User {
if (age < 0) throw new IllegalArgumentException("age < 0");
name = name.trim();
}
}
Initialization order
When new is called, the JVM performs these steps:
- Allocate memory; all fields set to default values (0 / null / false).
- Call the parent constructor (
super(...)), recursively up toObject. - Run field initializers and
{}initializer blocks, in the order they appear. - Run the body of the chosen constructor.
Common mistakes
- Forgetting to call
super(...)when the parent has no no-arg constructor. - Leaking
thisfrom a constructor (e.g. registering a listener) β the object isn't fully built yet. - Calling overridable methods from a constructor β in subclasses, those methods see half-initialized state.
- Doing too much work β constructors should set state, not load files or call remote APIs.
- Returning null from a factory
staticmethod β preferOptionalor an exception.
A good constructor is short, sets every required field, rejects invalid input, and leaves the object in a fully usable state. Treat it as the contract that every instance passes through.