Java Notes
Complete guide to Java constructors — default, parameterized, copy constructors, constructor chaining, overloading, and the role of constructors in object initialization.
A constructor is a special block of code that gets called automatically when you create an object using new. Its purpose is to initialize the object — to set up its initial state so it's ready to use.
Constructors are NOT methods. They look similar but have fundamental differences.
Constructor vs Method
| Feature | Constructor | Method |
|---|---|---|
| Name | Same as class name | Any valid identifier |
| Return type | None (not even void) | Must have one |
| Called | Automatically with new | Explicitly by programmer |
| Purpose | Initialize object state | Perform operations |
| Inherited | No | Yes |
this() / super() | Can call other constructors | Cannot |
Default Constructor
If you don't write any constructor, Java provides one automatically. It takes no parameters and sets all fields to their default values.
public class Book {
String title;
String author;
int pages;
double price;
boolean inStock;
// Java provides this implicitly:
// public Book() { }
}
public class Main {
public static void main(String[] args) {
Book book = new Book(); // Default constructor called
System.out.println("Title: " + book.title); // null
System.out.println("Author: " + book.author); // null
System.out.println("Pages: " + book.pages); // 0
System.out.println("Price: " + book.price); // 0.0
System.out.println("In Stock: " + book.inStock); // false
}
}Title: null Author: null Pages: 0 Price: 0.0 In Stock: false
Default values by type:
| Type | Default Value |
|---|---|
int, short, byte, long | 0 |
float, double | 0.0 |
boolean | false |
char | '\u0000' (null character) |
| Object references | null |
Important: The moment you define ANY constructor, Java stops providing the default one!
public class Book {
String title;
// Custom constructor
public Book(String title) {
this.title = title;
}
}
// Now this FAILS:
Book book = new Book(); // ❌ Compile error! No no-arg constructor exists
Book book = new Book("Java"); // ✅ WorksParameterized Constructor
A constructor that accepts arguments to initialize fields with specific values:
public class Employee {
private String name;
private String department;
private double salary;
private int yearsOfExperience;
// Parameterized constructor
public Employee(String name, String department, double salary, int yearsOfExperience) {
this.name = name;
this.department = department;
this.salary = salary;
this.yearsOfExperience = yearsOfExperience;
}
public void displayInfo() {
System.out.println("Name: " + name);
System.out.println("Department: " + department);
System.out.println("Salary: $" + salary);
System.out.println("Experience: " + yearsOfExperience + " years");
System.out.println("---");
}
}
public class Main {
public static void main(String[] args) {
Employee e1 = new Employee("Alice", "Engineering", 95000, 5);
Employee e2 = new Employee("Bob", "Marketing", 75000, 3);
e1.displayInfo();
e2.displayInfo();
}
}Name: Alice Department: Engineering Salary: $95000.0 Experience: 5 years
Constructor Overloading
You can have multiple constructors with different parameter lists, giving users flexibility in how they create objects:
red rectangle [5.0 x 3.0] area=15.0 white rectangle [4.0 x 7.0] area=28.0 white rectangle [6.0 x 6.0] area=36.0 white rectangle [1.0 x 1.0] area=1.0
Constructor Chaining with this()
Constructor chaining means one constructor calling another in the same class. This avoids code duplication:
public class Customer {
private String name;
private String email;
private String phone;
private String address;
private String membershipType;
// Main constructor - all initialization happens HERE
public Customer(String name, String email, String phone,
String address, String membershipType) {
this.name = name;
this.email = email;
this.phone = phone;
this.address = address;
this.membershipType = membershipType;
System.out.println("Customer created: " + name);
}
// Chain to main constructor
public Customer(String name, String email, String phone) {
this(name, email, phone, "Not provided", "Basic");
}
// Chain further
public Customer(String name, String email) {
this(name, email, "Not provided");
}
// Minimal info
public Customer(String name) {
this(name, "unknown@email.com");
}
}Rules for this():
- Must be the FIRST statement in the constructor
- Can only call ONE other constructor
- Cannot create circular chains (A calls B calls A)
Copy Constructor
Java doesn't have a built-in copy constructor like C++, but you can write one:
public class Address {
private String street;
private String city;
private String zipCode;
public Address(String street, String city, String zipCode) {
this.street = street;
this.city = city;
this.zipCode = zipCode;
}
// Copy constructor
public Address(Address other) {
this.street = other.street;
this.city = other.city;
this.zipCode = other.zipCode;
}
@Override
public String toString() {
return street + ", " + city + " " + zipCode;
}
}
public class Person {
private String name;
private int age;
private Address address;
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
// Deep copy constructor
public Person(Person other) {
this.name = other.name;
this.age = other.age;
this.address = new Address(other.address); // Deep copy!
}
@Override
public String toString() {
return name + ", age " + age + ", lives at " + address;
}
}
public class Main {
public static void main(String[] args) {
Address addr = new Address("123 Main St", "Springfield", "62701");
Person original = new Person("Alice", 30, addr);
Person copy = new Person(original); // Deep copy
System.out.println("Original: " + original);
System.out.println("Copy: " + copy);
System.out.println("Same object? " + (original == copy)); // false
}
}Original: Alice, age 30, lives at 123 Main St, Springfield 62701 Copy: Alice, age 30, lives at 123 Main St, Springfield 62701 Same object? false
Constructor with Validation
Constructors are the perfect place to validate data:
Boiling: 100.00°C / 212.00°F / 373.15K Body: 37.00°C / 98.60°F / 310.15K Space: -270.45°C / -454.81°F / 2.70K Error: Temperature cannot be below absolute zero (-273.15°C)
Private Constructor
Making a constructor private prevents external instantiation. Used for:
// Singleton Pattern - only one instance exists
public class DatabaseConnection {
private static DatabaseConnection instance;
private String connectionUrl;
// Private constructor - cannot be called from outside
private DatabaseConnection(String url) {
this.connectionUrl = url;
System.out.println("Connected to: " + url);
}
// Controlled access through static method
public static DatabaseConnection getInstance() {
if (instance == null) {
instance = new DatabaseConnection("jdbc:mysql://localhost:3306/mydb");
}
return instance;
}
public void query(String sql) {
System.out.println("Executing: " + sql);
}
}
public class Main {
public static void main(String[] args) {
// DatabaseConnection db = new DatabaseConnection("..."); // ❌ Cannot!
DatabaseConnection db1 = DatabaseConnection.getInstance();
DatabaseConnection db2 = DatabaseConnection.getInstance();
System.out.println("Same instance? " + (db1 == db2)); // true
db1.query("SELECT * FROM users");
}
}Connected to: jdbc:mysql://localhost:3306/mydb Same instance? true Executing: SELECT * FROM users
Constructor Execution Order
When inheritance is involved, constructors execute from parent to child:
public class Animal {
public Animal() {
System.out.println("1. Animal constructor");
}
}
public class Mammal extends Animal {
public Mammal() {
super(); // Implicitly added by compiler if missing
System.out.println("2. Mammal constructor");
}
}
public class Dog extends Mammal {
public Dog() {
super();
System.out.println("3. Dog constructor");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
}
}1. Animal constructor 2. Mammal constructor 3. Dog constructor
Instance Initializer Block
Code that runs before the constructor:
public class InitDemo {
private int value;
// Instance initializer block - runs before EVERY constructor
{
value = 42;
System.out.println("Instance initializer: value = " + value);
}
public InitDemo() {
System.out.println("No-arg constructor: value = " + value);
}
public InitDemo(int value) {
this.value = value;
System.out.println("Parameterized constructor: value = " + this.value);
}
}
public class Main {
public static void main(String[] args) {
new InitDemo();
System.out.println("---");
new InitDemo(100);
}
}Instance initializer: value = 42 No-arg constructor: value = 42 --- Instance initializer: value = 42 Parameterized constructor: value = 100
Common Mistakes
- Adding a return type to constructor:
```java // This is NOT a constructor — it's a method named "Car"! public void Car(String brand) { } // ❌ void makes it a method
// This IS a constructor public Car(String brand) { } // ✅ No return type ```
- Forgetting
this.:
``java public Employee(String name, double salary) { name = name; // ❌ Assigns parameter to itself this.name = name; // ✅ Assigns parameter to field } ``
- Constructor not accessible:
``java class Helper { Helper() { } // Package-private! Not accessible from other packages } ``
- Not providing no-arg constructor when needed:
``java public class Parent { public Parent(int x) { } // Only parameterized constructor } public class Child extends Parent { public Child() { // ❌ Implicit super() fails! Parent has no no-arg constructor super(0); // ✅ Must explicitly call parent's constructor } } ``
- Heavy logic in constructors:
``java // ❌ Don't do this - makes testing hard public UserService() { this.database = new Database(); this.cache = new Redis(); this.emailClient = new SMTPClient(); this.loadConfigFromNetwork(); } ``
Best Practices
- Validate parameters — Throw
IllegalArgumentExceptionfor invalid input - Keep constructors simple — Initialize fields, avoid complex logic
- Use constructor chaining — Avoid duplicate initialization code
- Consider builder pattern — When you have many optional parameters
- Make fields
finalwhen possible — Initialize in constructor, never change - Document parameter constraints — Use Javadoc to explain valid ranges
Interview Questions
Q1: Can a constructor be private? Yes. Used for Singleton pattern, utility classes (Math, Collections), and factory method pattern where object creation is controlled.
Q2: Can a constructor throw exceptions? Yes. This is useful for validation — if parameters are invalid, throw IllegalArgumentException before the object is fully created.
Q3: What is constructor chaining? Calling one constructor from another using this() (same class) or super() (parent class). It must be the first statement.
Q4: Can a constructor be final, static, or abstract? No. final — constructors aren't inherited, so final is meaningless. static — constructors work on instances, not class level. abstract — constructors must have a body to initialize objects.
Q5: What happens if you define a method with the class name? It becomes a regular method (with a return type), not a constructor. It won't be called by new.
Q6: How many constructors can a class have? Any number, as long as they have different parameter lists (different number or types of parameters).
Q7: Can you call a constructor explicitly? Not directly. You can call it via this() from another constructor, or via new ClassName(). You cannot call a constructor like a regular method.
Q8: What is the difference between constructor and instance initializer block? Instance initializer block runs before every constructor and is useful when multiple constructors share common initialization logic. The constructor runs after the initializer block. Execution order: parent constructor → instance initializer → constructor body.
Q9: Can we have a return statement in a constructor? You can have an empty return; statement (without a value) in a constructor to exit early, but you cannot return a value since constructors have no return type. Using return; is rare and generally discouraged.
Q10: What is the Builder pattern and why is it preferred over many constructors? Builder pattern creates objects step-by-step using method chaining: new Car.Builder().brand("BMW").year(2024).build(). It's better than telescoping constructors when there are many optional parameters because it's readable, prevents parameter ordering mistakes, and produces immutable objects.
Q11: What happens when a constructor throws an exception? The object is partially constructed and never fully initialized. The reference will be null (or the variable unassigned). The memory allocated is eligible for garbage collection. This is actually useful for validation — rejecting invalid objects at creation time.
Q12: What is the difference between this() and super() in constructors? this() calls another constructor in the same class (constructor chaining within class). super() calls the parent class constructor (initializing inherited portion). Both must be the first statement, so you cannot use both in the same constructor — but this() eventually chains to a constructor that calls super().
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Constructor in Java.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Java Master Course topic.
Search Terms
java-master-course, java master course, java, master, course, oops, constructor, constructor in java
Related Java Master Course Topics