Unit 1.13: Object Creation
Constructors
A class contains constructors, which are special blocks of code called to create (instantiate) and initialize objects.
- A constructor is a special type of method that has no return type and shares the same name as the class. It is responsible for setting the initial values of an object's instance variables.
Key Characteristics:
- Name: A constructor must have the exact same name as the class.
- No Return Type: Constructors do not have a return type, not even
void. - Initialization: Their primary purpose is to set the initial state of an object (i.e., initialize instance variables).
Task: Defining a no-argument constructor.
public class Player {
private int score;
// VALID: Matches class name, no return type
public Player() {
score = 0;
}
// INVALID: 'void' makes it a method, not a constructor
public void Player() { ... }
}
Default Constructors
Until now, in earlier chapters, you were able to construct an instance using the new keyword without writing a constructor yourself (e.g., new Book()). This is possible because of the default constructor.
- If no constructor is written, the compiler provides a hidden one that takes no arguments. This allows you to create simple objects immediately.
- Automatic Creation: If you do not define any constructors in your class, the Java compiler automatically provides a default no-argument constructor.
Task: Using the hidden default constructor.
public class SimpleObject {
// No constructors defined here
}
// In main:
SimpleObject s = new SimpleObject(); // Works! Uses the hidden default constructor
- Disappearing Act: However, once you define any constructor (with or without arguments), the compiler stops providing the default one. If you still want a no-argument constructor, you must define it explicitly.
Task: Observing how custom constructors disable the default one.
public class Smartphone {
private String model;
// We define a custom constructor
public Smartphone(String modelName) {
model = modelName;
}
}
// In main:
Smartphone phone1 = new Smartphone("Galaxy"); // OK: Matches custom constructor
Smartphone phone2 = new Smartphone(); // ERROR: Default constructor is GONE!
Constructor Parameters
Parameters allow constructors to receive initial values for an object's attributes. This allows each object to be created with its own unique data.
When you define a constructor, you specify variables in the parentheses (the header). These are local variables that hold the values passed in when new is called. Inside the constructor body, you typically assign these values to the object's instance variables.
Task: Passing initial values to a constructor.
public class User {
// Instance Variable (Attribute)
String username;
// Constructor with one parameter
public User(String name) {
// 'name' is the parameter (local variable)
// 'username' is the instance variable
// We assign the value from the parameter TO the instance variable
username = name;
}
}
Constructor Signature
A constructor's signature consists of its name and the ordered list of its parameter types. Java uses this signature to determine which constructor to call.
- Part of Signature: The name (e.g.,
User) and the types/order of parameters (e.g.,String, int). - NOT Part of Signature: The names of the parameters (e.g.,
name,age) and access modifiers (e.g.,public).
// Signature: User(String)
public User(String name) { ... }
// Signature: User(String, int)
public User(String name, int age) { ... }
// This would cause an ERROR because it has the same signature: User(String)
// public User(String email) { ... }
Overloading Constructors
Constructors are overloaded when a class has multiple constructors with different signatures.
- Overloading provides multiple ways to initialize an object. Depending on the arguments provided during instantiation, Java picks the constructor with the matching signature.
This provides flexibility, allowing you to create objects in different ways depending on what data you have available.
How it works:
When you use the new keyword, Java looks at the arguments you provide and matches them to the constructor with the corresponding signature.
Task: Defining multiple constructors for a class.
public class Rectangle {
int width, height;
// Constructor 1: Signature Rectangle()
public Rectangle() {
width = 1;
height = 1;
}
// Constructor 2: Signature Rectangle(int)
public Rectangle(int side) {
width = side;
height = side;
}
// Constructor 3: Signature Rectangle(int, int)
public Rectangle(int w, int h) {
width = w;
height = h;
}
}
// Usage:
Rectangle r1 = new Rectangle(); // Calls Constructor 1
Rectangle r2 = new Rectangle(5); // Calls Constructor 2
Rectangle r3 = new Rectangle(10, 20); // Calls Constructor 3
Constructor Arguments
When calling a constructor, the values you pass are called arguments. These arguments are passed by value to the constructor's parameters.
Putting it all together, here is an example:
Task: Reviewing a complete class with overloaded constructors.
class Book {
private String title;
private String author;
private double price;
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return this.title;
}
// default no argument constructor.
// Need not define if there are no other constructors defined.
public Book() {
}
// Constructor which takes one argument: title.
// The instance variable 'title' is initialized in this constructor.
public Book(String title) {
this.title = title;
}
// Constructor which takes two arguments: title and author.
// The instance variables 'title' and 'author' are initialized in this constructor.
public Book(String title, String author) {
this.title = title;
this.author = author;
}
public static void main(String[] args) {
Book book1 = new Book();
book1.setTitle("Harry Potter and the Sorcerer's Stone");
System.out.println(book1.getTitle());
Book book2 = new Book("Harry Potter and the Prisoner of Azkaban");
System.out.println(book2.getTitle());
}
}
Output:
Harry Potter and the Sorcerer's Stone Harry Potter and the Prisoner of Azkaban
In the above example, there are three constructors defined for the Book class:
- No-argument constructor: This is defined explicitly here because other constructors exist.
- One-argument constructor: The argument value 'title' initializes the instance variable 'title' when this constructor is invoked.
- Two-argument constructor: The argument values for 'title' and 'author' initialize the corresponding instance variables when this constructor is invoked.
Exercise: Can you add one more constructor which takes three arguments 'title', 'author' and 'price' ?
Notice the output of the program. You did not have to set the title using the setter method when you used the second constructor. You add additional constructors when you have all the variable values right at the time the object is instantiated. That way you initialize the values through the constructors and save yourself from adding many setter statements in the code.
The new Keyword
An object is created using the new keyword followed by a call to a constructor. This process is called instantiation.
private Constructors
Note: A constructor can be made private in which case you cannot instantiate the object using that constructor outside of the class. Typically this technique is used in Singleton Design Pattern that is out of scope of this eBook.
- A class contains 0 to more constructors using which an object can be created. If there are no constructors defined then a default, no argument constructor, is used from the top level Object Class.
- A class contains 0 to more instance variables that are used to hold the state of the object that is created from this class.
- A Class contains 0 to more methods which represent action that the object created from this class can take.
- Main method is not the method that is meant for object usage. Main method is only used for starting your program from the command line.
The null Reference
A reference variable can hold the special value null if it is not pointing to any object.
nullindicates that a reference variable is currently empty. It does not point to any memory address yet.
Task: Initializing a reference to null.
// This Book reference does not point to any object yet.
Book myBook = null;
Common Error: NullPointerException
If you try to call a method on a reference that is null, the program will crash with a NullPointerException.
Book myBook = null;
// This line causes a runtime error (crash) because myBook points to nothing!
// System.out.println(myBook.getTitle());
Safe Usage
You should often check if a reference is null before using it.
Task: Safely checking for null before use.
if (myBook != null) {
System.out.println(myBook.getTitle());
} else {
System.out.println("No book selected.");
}
Constructor Flow of Control
When you see a statement like new Book(...), the program's sequential execution is temporarily "paused" to build the object.
Step-by-Step Execution:
- Interrupt: The main program stops at the
newkeyword. - Jump: Control jumps to the matching constructor definition in the
Bookclass. - Execute: The code inside the constructor body runs (e.g., initializing variables).
- Return: Once the constructor finishes, control returns to the main program.
- Assign: The reference to the newly created object is assigned to the variable (e.g.,
book1).
Task: Tracing the flow of control during instantiation.
public class Bookstore {
public static void main(String[] args) {
System.out.println("Starting...");
// Control jumps FROM here TO the Book constructor
Book book1 = new Book("The Hobbit", "J.R.R. Tolkien");
// Control returns HERE after the object is fully built
System.out.println("Created book: " + book1.title);
}
}