Appearance
Constructors In Depth
Constructors are one of the most heavily tested topics in Java interviews. Before you finish reading this article, you will have a clear answer to every common interview question about constructors, and more importantly, you will understand the reasoning behind each rule so you never have to memorize anything blindly.
What a Constructor Actually Does
Think about building a house. Before anyone can live in it, two things must happen: the house has to be physically built, and it has to be furnished with the basics so it is actually usable. A constructor does exactly the same two things for a Java object: it creates the instance and it initializes the instance variables.
Every time you write new SomeClass(), Java calls the constructor for that class. The constructor's job is to bring the object into a valid, initialized state so that the rest of your code can safely use it.
A constructor looks a lot like a method, and that similarity trips people up. But three rules make a constructor fundamentally different from any method:
- The constructor name must be identical to the class name.
- A constructor has no return type, not even
void. - A constructor cannot be declared
static,final,abstract, orsynchronized.
Does new create the object, or the constructor? A method is allowed to have the same name as the class, so new is what tells Java at runtime: call the constructor, not a method with that name. The constructor then creates and initializes the instance.
These rules exist for specific reasons, and interviewers like to check that you know them.
The Interview Questions You Must Know Cold
Why must the constructor name match the class name?
Java needs a fast, unambiguous way to identify constructors among all the other methods in a class. There might be hundreds of methods. The naming rule means the compiler can find the constructor instantly. No searching, no guessing.
There is a subtle trap here that interviewers use: a method can legally have the same name as its class. This is valid Java:
java
class Employee {
// This is a constructor (no return type)
Employee() {
System.out.println("I am the constructor");
}
// This is a regular METHOD with the same name (has return type)
void Employee() {
System.out.println("I am a method, not a constructor");
}
}The presence or absence of a return type is the only thing distinguishing the two. A constructor has no return type. A method named Employee must declare void or some other type. This is why the "no return type" rule matters so deeply.
Why does a constructor have no return type?
When you call new Employee(), Java creates an Employee object and hands it back to you. The constructor implicitly returns the newly created instance. Because this return is always the object itself, there is no need to declare a return type. Java handles it automatically.
If you wrote Employee Employee() { } with a return type, Java would treat it as a regular method, not a constructor. The absence of a return type is the precise signal that tells the compiler "this is a constructor."
Why can constructors not be static?
Two separate reasons, both fundamental.
First, a static method can only access static variables. It has no concept of this, no reference to any particular object. But a constructor's entire purpose is to initialize instance variables on a specific object. If the constructor were static, it could not touch any instance variable. The constructor would be useless.
Second, constructor chaining through super() and this() requires an instance context. A static context has no this, so chaining would be impossible.
Why can constructors not be final?
The final keyword prevents a method from being overridden by a subclass. For final to make any sense, a method must first be inheritable. Constructors are never inherited, so they can never be overridden. Applying final to something that cannot be overridden is meaningless, and Java simply does not allow it.
Why are constructors not inherited? Because the inheritance rule for constructors would break the name rule. Imagine Employee had a constructor called Employee(). If it were inherited by Manager, that class would have a constructor named Employee inside it, but the rule says a constructor must have the same name as its own class. A constructor named Employee inside Manager would be constructing an Employee, not a Manager. The whole system would fall apart.
Why can constructors not be abstract?
An abstract method has no body. The class declaring it is forcing some subclass to provide the implementation. But for that to work, the subclass must inherit the abstract method, provide a body, and override it. Constructors are never inherited, so no subclass can ever implement a parent's constructor. The abstract concept simply does not apply.
Can an interface have a constructor?
No. The rule for a constructor is that it creates an instance of the class it belongs to. You can never write new SomeInterface(). Interfaces cannot be instantiated directly, so there is no scenario in which an interface constructor would run. Interfaces have no constructors.
Can constructors be overridden?
No. Since constructors are not inherited, they cannot be overridden. However, you can overload constructors: multiple constructors in the same class with different parameter lists. That is a completely different thing.
The Four Types of Constructors
Default Constructor
When you write a class and define no constructors at all, Java silently inserts a no argument constructor called the default constructor. You will not see it in your source file, but if you compile the class and look at the decompiled bytecode, it is right there.
java
class Calculation {
// You wrote nothing here
}
// What Java actually compiles:
class Calculation {
Calculation() {
super(); // Java inserts this too
}
}Fields you did not initialize hold their zero values: int is 0, double is 0.0, boolean is false, any object reference is null. Strictly speaking, that zeroing is not done by the default constructor: the JVM zeroes the memory when new allocates the object, before any constructor runs. The default constructor only calls super() (and any field initializers you wrote run as part of it).
No Argument Constructor
A no argument constructor looks identical to the default constructor in structure, but you write it explicitly. The moment you write it yourself, you have the power to add initialization logic inside it.
java
class Calculation {
String name;
// No-arg constructor written explicitly
Calculation() {
this.name = "Default"; // your own initialization
System.out.println("Calculation object created");
}
}Parameterized Constructor
A parameterized constructor accepts arguments so callers can supply specific values at construction time.
java
class Employee {
private int employeeId;
private String name;
Employee(int employeeId, String name) {
this.employeeId = employeeId; // this.employeeId = field, employeeId = parameter
this.name = name;
}
}
Employee emp = new Employee(101, "Priya");Notice the use of this.employeeId. Without this, the line would be employeeId = employeeId, which assigns the parameter to itself and leaves the field untouched. The compiler does not warn you because the assignment is syntactically valid. This is one of the most common silent bugs beginners introduce.
Private Constructor
A private constructor means no code outside the class can call it, so nobody outside can create an object with new. The class keeps full control. It hands out objects through a public static method; the method must be static because the caller has no object yet to call it on.
java
class Calculation {
private Calculation() { } // only this class can call it
public static Calculation getInstance() {
return new Calculation(); // allowed: we are inside the class
}
}
Calculation c = Calculation.getInstance(); // the only way in from outside
// new Calculation(); // compile error outside the classThis is the base of the Singleton pattern, where getInstance() is changed to always return the same single object (covered in the Singleton chapter).
The Vanishing Default Constructor
This catches so many developers by surprise. The default constructor exists only when you write zero constructors of your own. The moment you define any constructor, even just one parameterized constructor, Java stops providing the default.
java
class Calculation {
String name;
// You define ONE parameterized constructor
Calculation(String name) {
this.name = name;
}
}
new Calculation("Priya"); // OK
new Calculation(); // compile error: constructor Calculation in class Calculation cannot be applied to given typesJava no longer provides the no argument constructor because you have taken over constructor definition yourself. If you still need both, you must write both explicitly:
java
class Calculation {
String name;
Calculation() {
this.name = "Default";
}
Calculation(String name) {
this.name = name;
}
}This matters in inheritance too. If a parent class has only a parameterized constructor and no no argument constructor, every child class must explicitly call super(arguments). You will see exactly why in the section on super().
Constructor Overloading
Like method overloading, a class can have several constructors with the same name but different parameter lists. new picks the one whose parameters match the arguments.
java
class Employee {
String name;
int employeeId;
Employee(String name) {
this.name = name; // this.name = the field, name = the parameter
this.employeeId = 0;
}
Employee(String name, int employeeId) {
this.name = name;
this.employeeId = employeeId;
}
}
new Employee("Priya"); // calls the first constructor
new Employee("Priya", 101); // calls the secondThere is no constructor overriding, because constructors are never inherited.
Constructor Chaining with this()
When a class has multiple overloaded constructors, you often end up writing the same initialization logic in each one. Constructor chaining with this() lets you avoid that duplication by having one constructor call another.
java
class Calculation {
String name;
int id;
String type;
// Three-arg constructor: does all the real work
Calculation(String name, int id, String type) {
this.name = name;
this.id = id;
this.type = type;
}
// Two-arg constructor: supplies a default for type, then chains to three-arg
Calculation(String name, int id) {
this(name, id, "basic"); // calls three-arg constructor
}
// One-arg constructor: supplies defaults for id and type, then chains
Calculation(int id) {
this("DefaultName", id); // calls two-arg constructor
// which in turn calls three-arg constructor
}
}When you call new Calculation(42), the chain runs: the one arg constructor calls the two arg constructor, which calls the three arg constructor, which sets all three fields. This is constructor chaining within the same class.
Constructor Chaining with super()
The this() call works within one class. super() works between a parent class and a child class.
Here is a critical fact that surprises many people: Java automatically inserts super() as the very first statement of every constructor that does not already have an explicit this() or super() call. You do not write it, but it is always there.
java
class Person {
Person() {
System.out.println("Person constructor runs");
}
}
class Manager extends Person {
Manager() {
// Java silently inserts: super();
System.out.println("Manager constructor runs");
}
}
new Manager();Output:
Person constructor runs
Manager constructor runsThe parent's constructor always runs before the child's constructor. This is not optional or configurable. Java enforces it because the child object includes all of the parent's fields, and those parent fields must be initialized before the child's constructor tries to use them.
If you have a three level hierarchy like Object -> Person -> Manager, the order is: Object constructor first, then Person, then Manager. Every class in Java ultimately inherits from Object, so Object's constructor is always the very first thing that runs.
The Parameterized Parent Problem
The automatic super() only works when the parent has a no argument constructor. The moment you give a parent class only a parameterized constructor, its no argument constructor vanishes (remember the vanishing default rule), and every child class must explicitly provide the arguments:
java
class Person {
private int employeeId;
Person(int employeeId) {
this.employeeId = employeeId;
// no no-arg constructor exists now
}
}
class Manager extends Person {
private int age;
Manager(int employeeId, int age) {
super(employeeId); // REQUIRED: tells Java how to construct the Person part
this.age = age; // Manager initializes its own fields
}
}If you forget super(employeeId), javac gives you:
error: constructor Person in class Person cannot be applied to given types;
required: int
found: no arguments(Eclipse phrases the same problem as "Implicit super constructor Person() is undefined".)
Java tried to insert the default super() automatically, found no no argument constructor in Person, and gave up. You must supply it yourself.
The division of responsibility is clean: the parent constructor initializes the parent's fields, and the child constructor initializes the child's own additional fields. Never reach into the parent's private fields from a child constructor. Use super(...) and let the parent handle its own initialization.
Putting It Together: A Complete Example
Here is a realistic example that demonstrates all the major constructor concepts together:
java
class Person {
protected int employeeId;
// Parameterized constructor in parent
Person(int employeeId) {
this.employeeId = employeeId;
System.out.println("Person constructor: id = " + employeeId);
}
}
class Manager extends Person {
private int age;
private String department;
// Full constructor: initializes everything
Manager(int employeeId, int age, String department) {
super(employeeId); // parent initializes its own field
this.age = age; // Manager initializes its own fields
this.department = department;
System.out.println("Manager constructor: age=" + age + " dept=" + department);
}
// Convenience constructor: supplies default department
Manager(int employeeId, int age) {
this(employeeId, age, "General"); // chains to full constructor
}
}
Manager m1 = new Manager(101, 35, "Engineering");
// Output:
// Person constructor: id = 101
// Manager constructor: age=35 dept=Engineering
Manager m2 = new Manager(102, 28); // uses default department
// Output:
// Person constructor: id = 102
// Manager constructor: age=28 dept=GeneralEvery concept covered in this article appears in that example: parameterized constructor, the vanishing default, super() to delegate parent initialization, and this() chaining.
Check yourself
- Name three ways a constructor differs from a method.
- When does Java add a default constructor, and when does it disappear?
- Why can a constructor not be
final,static, orabstract? - What does the compiler insert at the start of
Manager()if you write neitherthis(...)norsuper(...)? What happens ifPersonhas onlyPerson(int id)? - For
new Manager()whereManager extends Person, which constructor body runs first, and why? - Can a constructor be
private? Why would you do that? What doesnewdo?
Answers
- Same name as the class, no return type (not even
void), cannot bestatic/final/abstract/synchronized; also, constructors are not inherited. - Only when the class declares no constructors at all. Writing any constructor removes it.
finalandabstractare about overriding, and constructors are never inherited, so they cannot be overridden.staticmakes no sense because a constructor initializes a specific new object (this).super();. IfPersonhas no no-arg constructor, compilation fails:constructor Person in class Person cannot be applied to given types. Callsuper(id)explicitly.Person's. Java insertssuper()as the first line ofManager(), so the parent part of the object is built before the child part.- Yes, to stop outside code from creating objects; the class hands them out through a static method such as
getInstance()(the base of Singleton).newtells Java to call a constructor rather than a method with the same name.