Java Constructors Explained (Default, Parameterized, Copy)
backend
9 min read
Master Java constructors in 10 minutes - default, parameterized, copy, chaining, and the patterns senior devs actually use in production code.

Published By: Nelson Djalo | Date: April 9, 2026
If you've ever written new Employee() and wondered what actually happens between those parentheses, you're about to find out. Constructors are the entry point for every object in Java, and getting them right is the difference between clean, predictable code and objects that blow up the moment you touch them.
This post walks through every flavor of constructor you'll meet in real Java code - default, no-arg, parameterized, copy - plus chaining, inheritance, and the mistakes that trip up even experienced devs.
A constructor is a special method that runs automatically when you create an object with the new keyword. Its job is to initialize the object - set the initial values of its fields, allocate resources, and put the object into a valid state before anyone uses it.
Three things make a constructor different from a regular method: it has the same name as the class, it has no return type (not even void), and you can't call it directly after the object exists. Here's the simplest possible example:
public class Employee {
private String name;
public Employee() {
this.name = "Unknown";
}
}
Employee emp = new Employee(); // constructor runs here
If you don't write any constructor at all, Java quietly adds one for you. It takes no arguments, does nothing, and just calls super() to initialize the parent class. This is the default constructor, and it only exists when you've written zero constructors yourself.
public class Employee {
private String name;
private double salary;
}
// Java generates this behind the scenes:
// public Employee() { super(); }
Employee emp = new Employee(); // works fine
The moment you add any constructor with parameters, the default one disappears. That's a common gotcha - you write a parameterized constructor, then new Employee() stops compiling and you wonder what changed.
A no-arg constructor is one you write yourself that takes no parameters. It looks identical to the default constructor from the outside, but you control what happens inside. Use this when you want sensible defaults or when a framework like Hibernate or Jackson requires one.
public class Employee {
private String name;
private double salary;
private String department;
public Employee() {
this.name = "New Hire";
this.salary = 50000.0;
this.department = "Unassigned";
}
}
Frameworks that use reflection to build objects (JPA, Jackson, Spring) often need a public no-arg constructor so they can instantiate your class and then set fields one by one. If you forget it, you'll get cryptic errors like "No default constructor for entity".
A parameterized constructor takes arguments so the caller can supply values at creation time. This is the constructor you'll write most often - it forces the object to start life with all the data it needs.
public class Employee {
private String name;
private double salary;
private String department;
public Employee(String name, double salary, String department) {
this.name = name;
this.salary = salary;
this.department = department;
}
}
Employee alice = new Employee("Alice", 75000, "Engineering");
Notice the this keyword - it distinguishes the field this.name from the parameter name. If you're fuzzy on how this works, check out The 'this' Keyword in Java.
A copy constructor creates a new object by copying the fields of an existing one. Java doesn't give you this for free like C++ does - you write it yourself. It's the cleanest way to make a defensive copy when you don't want two references pointing at the same object.
public class Employee {
private String name;
private double salary;
private String department;
public Employee(String name, double salary, String department) {
this.name = name;
this.salary = salary;
this.department = department;
}
// Copy constructor
public Employee(Employee other) {
this.name = other.name;
this.salary = other.salary;
this.department = other.department;
}
}
Employee alice = new Employee("Alice", 75000, "Engineering");
Employee aliceClone = new Employee(alice);
Watch out for deep vs shallow copies. If your class has mutable fields like a List or another object, a shallow copy shares references. You'll usually want to copy those collections too.
Constructor overloading means writing multiple constructors with different parameter lists. Java picks the right one based on the arguments you pass. This lets callers build the same object several ways.
public class Employee {
private String name;
private double salary;
private String department;
public Employee() {
this("Unknown", 0.0, "Unassigned");
}
public Employee(String name) {
this(name, 50000, "Unassigned");
}
public Employee(String name, double salary, String department) {
this.name = name;
this.salary = salary;
this.department = department;
}
}
Each overload has a unique signature. The compiler picks the match at compile time based on the arguments you pass.
Notice in the example above how the first two constructors call this(...)? That's constructor chaining. One constructor delegates to another in the same class, keeping the initialization logic in one place. This is massively useful - if you ever need to change how an Employee gets built, you change it once.
public Employee() {
this("Unknown", 0.0, "Unassigned"); // calls the 3-arg constructor
}
Two rules to remember: this() must be the very first statement in the constructor, and you can't chain in a circle (constructor A calls B which calls A). The compiler will stop you.
When you extend another class, the parent's constructor always runs before yours. If the parent has a no-arg constructor, Java calls super() for you automatically. But if the parent only has parameterized constructors, you must call super(...) explicitly as the first line of your constructor.
public class Person {
protected String name;
public Person(String name) {
this.name = name;
}
}
public class Employee extends Person {
private double salary;
public Employee(String name, double salary) {
super(name); // must be the first statement
this.salary = salary;
}
}
For a deeper dive on inheritance calls, read Super Keyword in Java. You can't use this() and super() in the same constructor - pick one.
A private constructor blocks outside code from creating instances with new. This is how you build a singleton, a utility class with only static methods, or a class that must be created through a factory method.
public class DatabaseConnection {
private static DatabaseConnection instance;
private DatabaseConnection() {
// set up the connection
}
public static DatabaseConnection getInstance() {
if (instance == null) {
instance = new DatabaseConnection();
}
return instance;
}
}
Utility classes like java.lang.Math use a private constructor so nobody can accidentally do new Math(). The private constructor is a clear signal: "don't instantiate this directly".
New Java devs sometimes blur the line between constructors and methods. Here's the cheat sheet:
void).new ClassName(). Methods are called on an object or class reference.If you accidentally give a "constructor" a return type, Java treats it as a regular method - and you'll spend an afternoon wondering why your fields aren't getting set.
Not initializing required fields. If your Employee needs a name to function, don't write a no-arg constructor that leaves it null. Either require it as a parameter or throw an exception.
Calling overridable methods from a constructor. When you call an overridable method inside a constructor, a subclass's version can run before the subclass's own constructor has finished. The subclass fields will still be default values. Make any method you call from a constructor private, static, or final.
public class Employee {
public Employee() {
init(); // DANGEROUS if subclasses override init()
}
protected void init() { /* ... */ }
}
Doing too much work. Constructors should initialize, not run heavy logic. Opening database connections, making HTTP calls, or starting threads from a constructor leads to objects that are hard to test and slow to build. Use a factory method or a separate start() call instead.
Forgetting the no-arg constructor for frameworks. JPA, Jackson, and many other libraries need a public no-arg constructor. If you only have a parameterized one, add the no-arg back explicitly.
Constructors decide how your objects are born, and good constructors mean valid objects from the first line. Stick to the patterns here - parameterized for required data, chaining to avoid duplication, private when you need control - and your code will be easier to reason about and harder to break.
Ready to go deeper into Java? The Java for Beginners course covers constructors, classes, and OOP from scratch, and the Java Master Class takes you through the advanced patterns you'll need on the job.
Can a constructor be final, static, or abstract?
No to all three. Constructors can't be inherited or overridden, so final and abstract make no sense. static is forbidden because constructors always run on an instance being created, not on the class itself.
Can a constructor return a value?
No. Constructors have no return type. If you add one (even void), Java treats your "constructor" as a regular method with the same name as the class, which almost always causes bugs.
What happens if I don't call super() in a child class constructor?
Java inserts super() automatically, calling the parent's no-arg constructor. If the parent has no no-arg constructor, compilation fails and you must call super(args) explicitly as the first statement.
Can I call one constructor from another in the same class?
Yes - use this(args) as the first statement. This is constructor chaining and it's the cleanest way to avoid duplicating initialization logic across overloaded constructors.
Why does Hibernate need a no-arg constructor?
Hibernate creates entity objects via reflection, then populates fields one at a time from the database. It needs to call new YourEntity() with no arguments before it knows any of the data. Always include a public or protected no-arg constructor on JPA entities.

Skip the generic recommendations. These 9 books changed how I write code, lead teams, and think about systems - from Clean Code to books most devs haven't heard of.

The exact skills, tools, and learning order to go from zero to hired as a Java full stack developer. Covers Spring Boot, React, databases, Docker, and what employers actually look for.

Abstract class or interface? Most Java devs get this wrong. Here's a clear breakdown with a side-by-side comparison table, code examples, and a simple decision rule.
Join thousands of developers mastering in-demand skills with Amigoscode. Try it free today.