Java tutorials  /  Java Constructors
Chapter 10 · Java

Java Constructors

A constructor in Java is a special block of code, resembling a method, that is automatically invoked when an object of a class is instantiated using the 'new' keyword. Its primary purpose is to initialize the newly created object's fields, and it shares its name exactly with the class and has no return type, not even 'void'.

Think of a constructor like the setup process when you first unbox and turn on a brand new smartphone. Before you can use it normally, it needs an initial setup step — setting your language, connecting to WiFi, entering your name — which happens automatically the moment you first power it on. A constructor is exactly this: the guaranteed initialization step that runs automatically the instant an object is created, ensuring it starts in a valid, ready-to-use state rather than an empty or broken one.

Consider an e-commerce system creating an 'Order' object every time a customer checks out. The Order class's constructor might require essential parameters like 'customerId', 'orderItems', and 'shippingAddress' to be provided immediately upon creation, guaranteeing that no 'Order' object can ever exist in an incomplete or invalid state (e.g., an order with no items or no shipping address). This immediate, mandatory initialization through a parameterized constructor is a common real-world pattern used to enforce critical business rules and data integrity right from the moment an object comes into existence.

Without constructors, objects would be created with all their fields left at Java's default values (0, false, null), often leaving the object in a meaningless or unusable state until manually set up through a series of separate setter calls afterward, during which time the object could be used incorrectly in its 'empty' state. Constructors solve this by guaranteeing that necessary setup and validation logic run atomically at the exact moment of object creation, ensuring every object is properly initialized and ready to be used safely and correctly from the very first line of code that has access to it.

  • Default Constructor: A no-argument constructor automatically provided by the Java compiler if a class defines no constructors at all, which simply initializes fields to their default values (0, null, false) with no custom logic.
  • No-Argument Constructor (Explicit): A constructor explicitly written by the developer that takes no parameters, but still allows custom initialization logic to run, unlike the compiler-generated default constructor.
  • Parameterized Constructor: A constructor that accepts one or more parameters, allowing the calling code to supply specific initial values for the object's fields at the moment of creation.
  • Copy Constructor: A constructor that accepts an existing object of the same class as its parameter and initializes the new object's fields by copying values from that existing object, effectively creating a duplicate.
class ClassName { dataType fieldName; // Constructor (same name as class, no return type) ClassName(dataType parameterName) { this.fieldName = parameterName; } } // Object creation invokes the constructor: ClassName obj = new ClassName(value);
A beginner wants to create a 'Book' class where every book object must have a title and price set immediately upon creation, and also wants a way to create a new book by simply copying the details of an existing book object, requiring both a parameterized constructor and a copy constructor.
Parameterized Constructor for Guaranteed Initialization
This example defines a Book class with a parameterized constructor that requires a title and price to be provided immediately when creating any Book object, preventing incomplete object states.
Java
class Book { String title; double price; public Book(String title, double price) { this.title = title; this.price = price; } } public class BookDemo { public static void main(String[] args) { Book myBook = new Book("Effective Java", 45.99); System.out.println("Title: " + myBook.title); System.out.println("Price: " + myBook.price); } }
Title: Effective Java Price: 45.99
The constructor 'public Book(String title, double price)' has the exact same name as the class 'Book' and no return type at all. The 'this.title = title;' line uses the 'this' keyword to distinguish the class's field ('this.title') from the constructor's parameter of the same name ('title'), assigning the passed-in value to the actual object field. Since Book only defines this parameterized constructor, calling 'new Book();' with no arguments would now cause a compile-time error, since the compiler no longer provides its automatic default constructor once any constructor is explicitly defined.
Constructor Overloading and Chaining with this()
This example demonstrates multiple overloaded constructors within the same class, using the 'this()' keyword to chain from a simpler constructor to a more complete one, avoiding duplicated initialization logic.
Java
class Employee { String name; double salary; public Employee(String name) { this(name, 30000.0); } public Employee(String name, double salary) { this.name = name; this.salary = salary; } } public class ChainingDemo { public static void main(String[] args) { Employee emp1 = new Employee("Alice"); Employee emp2 = new Employee("Bob", 55000.0); System.out.println(emp1.name + ": " + emp1.salary); System.out.println(emp2.name + ": " + emp2.salary); } }
Alice: 30000.0 Bob: 55000.0
The single-parameter constructor 'Employee(String name)' uses 'this(name, 30000.0);' as its very first statement to call the two-parameter constructor, passing along the given name and a default salary of 30000.0. This is called constructor chaining, and it avoids duplicating the actual field-assignment logic in more than one place; the 'this()' call, when used, must always be the first statement inside a constructor.
  • Adding a Return Type to a Constructor: Accidentally writing 'void Book(String title)' instead of 'Book(String title)' causes Java to interpret this as a regular method named 'Book' that happens to share the class's name, NOT a constructor. This 'method' would need to be explicitly called after object creation and would not run automatically during 'new Book(...)', which silently breaks the intended automatic-initialization behavior without necessarily causing an immediate compile error.
  • Assuming the Default Constructor Still Exists After Adding a Custom One: Once a class defines ANY constructor explicitly (even just a parameterized one), Java no longer automatically provides its free no-argument default constructor. Beginners are often surprised when 'new MyClass();' (with no arguments) suddenly fails to compile after they've added a parameterized constructor, not realizing the implicit default constructor was silently removed the moment they wrote their own.
  • Forgetting 'this' Keyword Causes Field Shadowing Confusion: Writing 'title = title;' inside a constructor where the parameter name matches the field name does NOT assign the parameter's value to the object's field at all — it actually just reassigns the parameter variable to itself (a no-op), leaving the object's actual field at its default value (like null for a String). The 'this.title = title;' syntax is required to explicitly refer to the object's field when parameter names intentionally match field names.
  • Placing this() or super() Calls in the Wrong Position: Attempting to place a 'this()' or 'super()' constructor-chaining call anywhere other than the very first line of a constructor results in a compile-time error: 'call to this must be first statement in constructor' (or similarly for super). Java strictly requires these chaining calls to occur before any other initialization logic runs within that constructor.
  • Use Constructor Chaining to Avoid Duplicated Initialization Logic: When a class has multiple overloaded constructors that share common initialization steps, use 'this(...)' to chain from simpler constructors to the most complete one, centralizing the actual field-assignment logic in a single place rather than repeating it across every overloaded constructor.
  • Validate Parameters Inside Constructors: Add validation logic directly within constructors to reject invalid initial states immediately (e.g., throwing an 'IllegalArgumentException' if a negative price is passed to a Book constructor), ensuring objects can never exist in a semantically invalid state from the very moment of their creation.
  • Prefer Parameterized Constructors Over Setter-Based Initialization for Mandatory Fields: For fields that are absolutely required for an object to make sense (like an Order's customerId), enforce their initialization through a parameterized constructor rather than relying on separate setter method calls after object creation, which could leave a brief window where the object exists in an incomplete, invalid state.
  • Consider the Builder Pattern for Classes with Many Optional Parameters: When a class has numerous optional fields, leading to many overloaded constructors (a situation known as 'telescoping constructors'), consider using the Builder design pattern instead, which provides a much more readable and flexible way to construct objects with many optional parameters without an overwhelming number of overloaded constructor combinations.
What is the key difference between a constructor and a regular method in Java?
A constructor must share the exact same name as its class and has absolutely no return type, not even 'void' — including a return type turns it into a regular method instead, even if it shares the class's name. A constructor is automatically and implicitly invoked exactly once, at the moment an object is created using the 'new' keyword, whereas a regular method must be explicitly called whenever needed and can be called any number of times (or never at all) throughout an object's lifetime. Constructors are specifically used for object initialization, while regular methods define general behavior an object can perform after it has already been initialized.
What happens to Java's automatically-provided default constructor once you add your own parameterized constructor to a class?
Java's compiler only automatically generates a no-argument default constructor if a class defines absolutely no constructors of its own. The moment a developer explicitly writes even a single constructor (parameterized or not), the compiler's automatic default constructor generation is suppressed entirely. This means if you only define a parameterized constructor and still need a no-argument way to create objects of that class, you must explicitly write your own no-argument constructor as well — it will no longer be provided for free.
Explain constructor chaining using 'this()' in Java, and state the key rule governing where it must be placed.
Constructor chaining using 'this(...)' allows one constructor within a class to call another overloaded constructor of the SAME class, passing along some or all of its parameters, typically to supply sensible default values for parameters not provided to the simpler constructor. This avoids duplicating the actual field-initialization logic across multiple overloaded constructors, centralizing it in one place. The critical rule is that if a 'this(...)' call is used, it MUST be the absolute first statement inside the constructor — no other code, not even a simple print statement, can precede it, and violating this rule results in a compile-time error.
Create a 'Rectangle' class with a parameterized constructor accepting length and width, and a copy constructor that creates a new Rectangle object by copying values from an existing Rectangle object. Demonstrate both in a main method.
class Rectangle { double length, width; public Rectangle(double length, double width) { this.length = length; this.width = width; } public Rectangle(Rectangle other) { this.length = other.length; this.width = other.width; } } public class CopyConstructorDemo { public static void main(String[] args) { Rectangle original = new Rectangle(10.0, 5.0); Rectangle copy = new Rectangle(original); System.out.println("Original: " + original.length + " x " + original.width); System.out.println("Copy: " + copy.length + " x " + copy.width); } } // Output: // Original: 10.0 x 5.0 // Copy: 10.0 x 5.0
What is wrong with the following code, and what specific error will occur? class Product { String name; void Product(String name) { this.name = name; } } public class Test { public static void main(String[] args) { Product p = new Product("Laptop"); System.out.println(p.name); } }
The 'Product' method has a 'void' return type ('void Product(String name)'), which means Java treats it as a regular method that happens to share the class's name, NOT as an actual constructor. Because of this, Java still generates its own implicit default no-argument constructor for the Product class (since no true constructor was defined), so calling 'new Product("Laptop")' fails to compile with an error like 'constructor Product in class Product cannot be applied to given types', since the only real constructor available is the implicit no-argument one, which doesn't accept a String parameter. The fix is to remove the 'void' return type, making it 'Product(String name) { this.name = name; }', which correctly defines it as a genuine constructor.
Write a class 'Circle' with two overloaded constructors: one that takes a radius, and a no-argument constructor that chains to the parameterized one using this(), defaulting the radius to 1.0.
class Circle { double radius; public Circle() { this(1.0); } public Circle(double radius) { this.radius = radius; } } public class CircleDemo { public static void main(String[] args) { Circle defaultCircle = new Circle(); Circle customCircle = new Circle(5.0); System.out.println("Default radius: " + defaultCircle.radius); System.out.println("Custom radius: " + customCircle.radius); } } // Output: // Default radius: 1.0 // Custom radius: 5.0

Constructors are special, automatically-invoked blocks of code responsible for initializing an object's fields the moment it is created, sharing the class's exact name and having no return type at all. Java supports default, parameterized, and copy constructors, along with constructor overloading and chaining via 'this()' to avoid duplicated initialization logic. Understanding that the compiler's free default constructor disappears once any custom constructor is defined, and correctly using the 'this' keyword to resolve field-parameter naming conflicts, are essential skills for reliably initializing objects in real-world Java applications.

© 2026 CompileX. Maintained by Aditya Kumar Sharma.