Verified for the 2025 AP Computer Science A exam•Last Updated on June 18, 2024
Constructors are special methods that bring objects to life in Java. When you create a new object using the new
keyword, a constructor is called to initialize the object's state. In this section, we'll explore how constructors work, how they set initial values for instance variables, and how they establish the starting characteristics of an object. Understanding constructors is crucial for creating well-formed objects that begin their lifecycle in a proper, predictable state.
A constructor is a special method that:
void
)new
keywordTerms to know:
public class Student { private String name; private int id; private double gpa; // This is a constructor public Student(String name, int id) { this.name = name; this.id = id; this.gpa = 0.0; // Default starting value } } // Creating an object calls the constructor Student student1 = new Student("Alex Kim", 12345);
The primary purpose of constructors is to set the initial state of an object by:
This creates a "has-a" relationship between the object and its instance variables. For example, a Car
object "has a" model name, "has a" year, and "has a" current mileage.
Constructor parameters are local variables that:
public class Rectangle { private double length; private double width; public Rectangle(double length, double width) { // Parameters length and width provide values // for instance variables this.length and this.width this.length = length; this.width = width; } }
The this
keyword is used to distinguish between:
When parameter names match instance variable names (which is common), this
is necessary to avoid confusion:
public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; // this.name refers to the instance variable this.age = age; // age by itself would refer to the parameter } }
A class can have multiple constructors with different parameter lists, known as constructor overloading:
public class Book { private String title; private String author; private int pages; // Constructor for fully specified book public Book(String title, String author, int pages) { this.title = title; this.author = author; this.pages = pages; } // Constructor for unknown page count public Book(String title, String author) { this.title = title; this.author = author; this.pages = 0; // Unknown page count } // Constructor for anonymous work public Book(String title) { this.title = title; this.author = "Unknown"; this.pages = 0; } }
When no constructor is written for a class:
int
, double
, etc.): 0
false
null
// This class has no explicit constructor public class SimpleBox { private int width; private String label; private boolean isOpen; } // Java provides a default constructor SimpleBox box = new SimpleBox(); // box.width is 0 // box.label is null // box.isOpen is false
Important: If you define any constructor, Java will NOT provide the default constructor.
When a constructor parameter is a mutable object (an object that can be changed):
public class Course { private String name; private ArrayList<String> students; public Course(String name, ArrayList<String> roster) { this.name = name; // WRONG: Direct reference - changes to roster will affect students // this.students = roster; // CORRECT: Create a copy to prevent unwanted changes this.students = new ArrayList<String>(roster); } }
Consider this example:
// Create a roster ArrayList<String> classRoster = new ArrayList<String>(); classRoster.add("Emma"); classRoster.add("Noah"); // Create a course with this roster Course math101 = new Course("Math 101", classRoster); // Later, modify the original roster classRoster.clear(); // Remove all students // If Course used direct reference, math101 would now have no students! // By creating a copy, math101's student list is protected
Here's a complete example showing proper constructor usage:
public class BankAccount { private String accountNumber; private String ownerName; private double balance; private ArrayList<String> transactionHistory; public BankAccount(String accountNumber, String ownerName, double initialDeposit) { this.accountNumber = accountNumber; this.ownerName = ownerName; // Validate initial deposit if (initialDeposit >= 0) { this.balance = initialDeposit; } else { this.balance = 0; } // Initialize empty transaction history this.transactionHistory = new ArrayList<String>(); // Record initial deposit if positive if (initialDeposit > 0) { this.transactionHistory.add("Initial deposit: $" + initialDeposit); } } public BankAccount(String accountNumber, String ownerName) { // Call the other constructor with zero initial deposit this(accountNumber, ownerName, 0); } }
this
keyword to distinguish between instance variables and parameters with the same name