Opening subject page...
Loading your content
Learn how constructors initialize objects and establish the state every instance needs from the moment it is created.
Before object-oriented programming became mainstream, programs were organized as sequences of procedures that operated on separate data structures. A persistent source of bugs was uninitialized data—developers would allocate memory for a record and then forget to set one or more fields before using it. Languages like C required programmers to call an explicit initialization function after every allocation, and nothing in the compiler enforced that discipline. The idea of tying initialization logic directly to the act of creating an object arose as language designers sought to eliminate that entire class of defect.
The central question constructors answer is deceptively simple: how can a language guarantee that every object is properly initialized the instant it is created? Understanding constructors means understanding the contract between a class author and the clients who instantiate that class.
A constructor is a special method that is invoked automatically when an object is created with the new keyword. Unlike ordinary methods, a constructor shares the exact name of its class and has no return type—not even void. Its sole purpose is to establish the initial state of an object by assigning values to instance variables.
void ClassName() creates an ordinary method, not a constructor—a common exam pitfall.this(args) as the first statement. This avoids code duplication when multiple constructors share initialization logic.When the JVM encounters new Dog("Rex", 5), it first allocates raw memory on the heap for the new object and sets every instance variable to its type-default value (0 for numeric types, false for booleans, and null for reference types). Only then does the matching constructor execute, overwriting those defaults with the values the caller supplied. The expression as a whole evaluates to a reference to the now-initialized object, which is stored in the local variable d. This sequence is critical to understand because it explains why you can refer to this inside a constructor—the object already exists; the constructor is simply populating it.
A constructor declaration mirrors a method declaration in many ways but differs in two key aspects: it must share the class name exactly, and it must omit a return type. The general pattern is:
public so that external client code can instantiate the class. The parameter list defines what information callers must supply.If a class contains no explicitly written constructor, the Java compiler inserts a default no-argument constructor behind the scenes. This default constructor takes no parameters and leaves all instance variables at their type-default values. However, the moment you define any constructor—even one with parameters—the compiler stops providing the default. If client code later tries to call new ClassName() and no matching no-argument constructor exists, the compiler reports an error. This is a frequently tested concept on the AP exam.
Java allows a class to have multiple constructors as long as their parameter lists differ in number, type, or order. This is called constructor overloading. When the client writes new ClassName(args), the compiler matches the argument types to the correct constructor signature at compile time. Overloaded constructors allow flexible object creation: one might accept all field values, another might accept a subset and use defaults for the rest, and a no-argument version might create a "blank" instance.
When overloaded constructors share initialization logic, duplicating code in each one is fragile and hard to maintain. Java provides the this() call to delegate from one constructor to another within the same class. The rule is strict: this() must be the very first statement in the constructor body. For example, a no-argument constructor might call this("Unknown", 0) to delegate to the two-parameter version, keeping all initialization logic in a single place.
this(). The bottom panel highlights the compiler-generated default constructor and the rule that it vanishes once any explicit constructor is declared.| Constructor Type | When to Use | Example Call |
|---|---|---|
| No-argument | When a sensible default state exists for the object | new Dog() |
| Parameterized | When the caller must supply values to create a meaningful object | new Dog("Rex", 5) |
| Chained (this()) | When one constructor can delegate to another to avoid duplicated initialization code | this("Unknown", 0) |
| Compiler default | Automatically supplied when you write zero constructors; rarely relied upon intentionally | new Dog() (implicit) |
Let us design a BankAccount class that stores an owner's name and a balance. We will write a parameterized constructor, a no-argument constructor that chains to it, and trace through two instantiations.
private to enforce encapsulation.private String owner; private double balance;this.field = param to avoid shadowing.public BankAccount(String owner, double balance) { this.owner = owner; this.balance = balance; }this() must be the first statement.public BankAccount() { this("Unassigned", 0.0); }owner to null and balance to 0.0, then the parameterized constructor executes, assigning "Alice" and 500.0.owner = "Alice", balance = 500.0this("Unassigned", 0.0). The parameterized constructor runs and sets both fields.owner = "Unassigned", balance = 0.0| Pitfall | Why It Happens | Best Practice |
|---|---|---|
| Adding a return type to a constructor | Students write void Dog() thinking it is required—this creates an ordinary method, not a constructor | Omit the return type entirely; the compiler identifies constructors by matching the class name with no return type |
| Losing the default constructor | Defining a parameterized constructor causes the compiler's default no-arg constructor to vanish | Explicitly write a no-arg constructor if clients need one |
Parameter shadowing without this | A parameter with the same name as an instance variable hides the field; name = name assigns the parameter to itself | Use this.name = name to disambiguate |
Placing this() after other statements | Java requires this() to be the first executable statement in a constructor | Always place the this() call on the very first line |
| Constructors returning a value | Students try to return a value from a constructor | Constructors can contain a bare return; to exit early but never return a value |
Constructors become even more important once classes participate in inheritance hierarchies. When a subclass is instantiated, the subclass constructor must first invoke a constructor of its superclass—either explicitly via super(args) or implicitly via super(). If the superclass has no no-arg constructor, the subclass must call super(args) explicitly, or the code will not compile. This mirrors the earlier pitfall of losing the default constructor and is a heavily tested AP exam topic.
| Concept | this() | super() |
|---|---|---|
| Purpose | Calls another constructor in the same class | Calls a constructor in the parent class |
| Placement rule | Must be the first statement | Must be the first statement |
| Can coexist? | Cannot appear in the same constructor as super() | Cannot appear in the same constructor as this() |
| Implicit call | Never inserted by compiler | Compiler inserts super() if neither this() nor super() is written |
As you progress to the AP exam's inheritance and polymorphism units, you will see that constructor chaining cascades up the class hierarchy: the subclass constructor calls a superclass constructor via super(), which in turn may call Object(). Understanding how constructors work in isolation is the foundation for reasoning about these more complex scenarios.
public class Cat {
private String name;
private int lives;
public Cat(String name) {
this.name = name;
lives = 9;
}
}
Which of the following statements will cause a compile-time error?public class Point {
private int x;
private int y;
public Point(int x, int y) {
x = x;
y = y;
}
public String toString() {
return "(" + x + ", " + y + ")";
}
}
// In main:
System.out.println(new Point(3, 7));public class Book {
private String title;
private int pages;
public Book(String title, int pages) {
this.title = title;
this.pages = pages;
}
public Book(String title) {
this(title, 100);
}
}
What is the value of pages after executing Book b = new Book("Java");?Student class has instance variables private String name and private double gpa. Write (a) a two-parameter constructor that initializes both fields, and (b) a no-argument constructor that sets the name to "Unknown" and the gpa to 0.0 by chaining to the two-parameter constructor.Rectangle class with instance variables private double width and private double height.
(a) Write a two-parameter constructor that sets both dimensions. If either parameter is negative, the corresponding field should be set to 0.
(b) Write a one-parameter constructor that creates a square (both dimensions equal to the parameter) by chaining to the two-parameter constructor.
(c) Write a no-argument constructor that creates a 1 × 1 unit square by chaining to another constructor.
(d) Explain why you cannot place both a this() call and a super() call in the same constructor.