Skip to main content
Logo image

Section 8.3 Constructors

As we’ve seen, instance variables define the structure that all instances of a class share. And each object stores its own value for each instance variable in its object data. But how do those instances get created and how are their instance variables initialized?
That’s the job of the constructorβ€”to set the initial values for the object’s instance variables to useful values. But what does β€œuseful” mean? Sometimes we describe the values of all an object’s instance variables at a given time as the object’s state. And we say an object is in a valid state when all its instance variables have values that let us use the object by invoking its public methods.
So another way to describe the job of a constructor is to set the object’s instance values so it’s in a valid state and ready to be used. As we’ll see, classes can have zero or more constructors but they should all produce an object in a valid state.
For instance, it doesn’t really make sense to call greet on a Person object unless it’s name instance variable has been set. And canVote only works if age has been initialized. Which is why the constructor in the Person class takes arguments that let it initialize both of those variables.
As we’ll see, constructors are similar in many ways to methods: they can take arguments and contain code that is run when they are invoked. But unlike a method, a constructor is called exactly once for each object, when the object is created. This is in contrast to methods that can be called whenever we want, for as long as we have a reference to an object.
In the source code for a class, constructors are usually written after the instance variables and before any methods. Which make sense because first we need to see the instance variables to understand the basic structure of a class. But before we can look at methods and see how to use the class we need to see how those variables are initialized. And to understand that, we need to look at the classes constructors.

Subsection 8.3.1 Not writing a constructor

The simplest way to get a constructor is to not write one at all! If a class does not contain an explicit constructor, Java creates what is called the default constructor automatically. The default constructor takes no arguments and does nothing. But that doesn’t mean the object’s instance variables are not initialized.
Instance variables can be declared with and without initializers. Here’s a class that has one of each as well as an instance method to show their values and a main to instantiate an object and call the method.
public class Demo {
    private String a;
    private String b = "I have a value";

    public void showValues() {
        System.out.println("a: " + uninitialized);
        System.out.println("b: " + initialized);
    }

    public static void main(String[] args) {
        Demo d = new Demo();
        d.showValues();
    }
}
This will produce the output:
a: null
b: I have a value
We can see that both instance variables have a value but one of them is null. Every instance variable in an object has a value from the moment the object is created. To ensure that, if an instance variable declaration doesn’t assign a value, the variable will start out with the approriate zero value for its type, 0, 0.0, false, or null. But otherwise the variable is assigned the value specifed in the declaration. These assignments happen even before the constructor runs so code in the constructor can rely on instance variables being initialized.
One important note: if you do write a constructor, Java will not generate the default constructor for you. This is a good thing because it lets you make sure that instances of your class are always properly initialized. For example, because our Person class contains an explicit constructor, there’s no way to construct a Person object without providing the required name and age values so there will never be an instance of Person missing those values.

Note 8.3.1.

Technically someone could call our Person constructor like new Person(null, 0) but then they’d kind of get what they deserve. And some Java programmers, especiallly when working in large systems, would write the constructor to check that the arguments themselves are valid and to fail immediately if they are not.
In general it is good style to initialize variables in their declaration if possible. But that’s not always the case. Often we need information from the code that is constructing the object to know what the values in the object should be. In those cases we actually have to write a constructor.

Subsection 8.3.2 Constructor signatures

In SectionΒ 3.1Β Writing methods we learned about method signatures, the combination of the return type, method name, and parameters that identify a method. Constructors also have a signature but it is structured slightly differently.
The main difference is a constructor has no return type, not even void, and instead of a method name, the name of the constructor is always the same as the name of the class. This is because constructors don’t return a value; they initialize a brand new object. Here, for example, is the constructor from our Person class:
public Person(String name, int age) {
  this.name = name;
  this.age = age;
}
As we can see, there is no return type between public and Person. And Person is the name of the class this constructor came from. After the name comes a list of parameters which work just like parameters in a method: they are local variables that will hold the values of the arguments passed to the constructor. And constructors don’t need a return statement because they don’t return a value.
To invoke a constructor we use the keyword new, just like we did with arrays, but instead of specifying the type and dimensions of an array, we follow new with the class name and an argument list in parentheses that matches a constructor in that class. So to invoke the Person constructor above we would write an expression like:
new Person("Joe", 18);
When we invoke a constructor with new two things happen: first a new object is created and the memory needed to hold all its instance variables is allocated somewhere in the computer’s memory. Then, after the instance variable are initialized either to their default zero value or the value specified in the declaration, the constructor is run with this being the newly created object. The code in the constructor can then finish initializing the object however is appropriate. In the case of the above constructor invocation, the constructor will set the instance variable name to the value "Joe" and set age to 18. The value of a constructor invocation is a reference to the new object just like the value of an array creation expression is a reference to the newly created array.
Constructor signatures are an important part of the API when we use a class from a library someone else has written. In order to use most classes, such as the Turtle class we first used in SectionΒ 3.2Β APIs and Libraries we need to look up how to construct an instance of the class. Usually we’ll look at the class’s documentation which will list the signatures of the constructors available. Knowing the parameter list of a constructor gives us the information we need to invoke the constructor. The documentation may also give us more information about how the constructor’s arguments will be used or restrictions. For instance, in a real Person class, we might document that the age argument has to be a positive number.

Note 8.3.2.

Like classes, constructors will usually be made public. As with making a class public it means the constructor can be invoked from any code anywhere.
Constructors can also be private and sometimes that’s useful to control how instances of a class are created. And there is a level of accessibility inbetween public and private that requires a deeper understanding of Java packages than we want to get into. But both of those options are well outside the AP curriculum. For the purposes of the AP exam classes and their constructors are always public.
Constructors cannot have the static modifier that we’ve used with methods until this unit. That’s only an option for methods and variables which will discuss more in ChapterΒ 9Β Objects.

Subsection 8.3.3 Overloading constructors

It’s also possible to define more than one constructor in a class. As long as they all have different signatures, meaning the number or the types of their parameters are different, we can have as many constructors as we want. Such constructors are said to be overloaded.
One common reason to write overloaded constructors is when some of the instance variables in the class have reasonable default values. In such cases we can write one constructor that takes arguments for all the instance variables that need to be initialized and then write other constructors that omit certain parameters and instead initialize the unspecified variables to default values.
For instance, in our Person class, suppose we wanted to be able to make objects to represent anonymous people but we wanted all anonymous people to be named the same thing: "Anonymous". Rather than requiring all the code that wants to construct an anonymous Person to pass that specific String to the two-argument constructor we’ve already written, we can write a new constructor like this:
public Person(int age) {
    this.name = "Anonymous";
    this.age = age;
}
With that constructor added to the class, writing new Person(20) is the same as writing new Person("Anonymous", 20).
However there’s an even better way to write that constructor using the this keyword, that we’ve previously used to access instance variables. In the context of a constructor, we can use this followed by an argument list in parentheses to invoke another constructor’s code to let it initialize the object. So we could write that one-argument constructor like this:
public Person(int age) {
    this("Anonymous", age);
}
Then when we evaluate new Person(20) the argument 20 is passed to that constructor which then passes it along to the original constructor with the "Anonymous" as the name argument. In this case it doesn’t simplify things much since both constructors are so simple. But in more complicated classes that do more complicated initialization it lets us write the complicated stuff in just one place. The typical pattern for writing overloaded constructors is to write one main constructor that takes all the arguments that could possibly be passed, and then write other constructors that take fewer arguments and invoke the main constructor using this(), passing default values as needed.

Activity 8.3.1.

The following digram shows the signatures of two of the constructors in the Turtle class.
Turtle Class Constructor Signatures and Parameters
Figure 8.3.3. Turtle Class Constructor Signatures and Parameters
Given the Turtle class in the figure above and a World object world1, which of the following code segments will correctly create an instance of a Turtle object at x, y coordinates 50, 150?
  • Turtle t = new Turtle();
  • There is no Turtle constructor that takes no arguments according to the figure above.
  • Turtle t = new Turtle(50,150);
  • There is no Turtle constructor that takes 2 arguments according to the figure above.
  • Turtle t = new Turtle(world1);
  • This would initialize the Turtle to the middle of the world, not necessarily coordinates (50,150).
  • Turtle t = new Turtle(world1,50,150);
  • Make sure the order of the arguments match the constructor signature above.
  • Turtle t = new Turtle(50,150,world1);
  • This matches the second constructor above with the parameters of x, y, and world.
Another reason to overload constructors is to allow callers to construct objects with arguments of a type different than what the class really needs. As a trivial example, consider class that stores an ammount in an int variable. The obvious constructor would look like:
public Amount(int value) {
    this.value = value;
}
But maybe sometimes it’d be convenient to construct an amount from a String containing a numeric value. In that case we could write another constructor:
public Amount(String value) {
    this(Integer.parseInt(value));
}

Activity 8.3.2.

Activity 8.3.3.

Given the Date class in the previous problem and assuming that months in the Date class are numbered starting at 1, which of the following code segments will create a Date object for the date September 20, 2020 using the correct constructor?
  • Date d = new Date();
  • This would initialize the date attributes to today’s date according to the constructor comment above, which might not be Sept. 20, 2020.
  • Date d = new Date(9,20);
  • There is no Date constructor that takes 2 arguments according to the figure above.
  • Date d = new Date(9,20,2020);
  • The comment for the second constructor in the Date class above says that the first argument must be the year.
  • Date d = new Date(2020,9,20);
  • This matches the second constructor above with the parameters year, month, day.
  • Date d = new Date(2020,20,9);
  • Make sure the order of the arguments match the constructor signature above.

Activity 8.3.4.

Activity 8.3.5.

What best describes the purpose of a class’s constructor?
  • Determines the amount of space needed for an object and creates the object
  • The object is already created before the constructor is called but the constructor initializes the instance variables.
  • Names the new object
  • Constructors do not name the object.
  • Return to free storage all the memory used by this instance of the class.
  • Constructors do not free any memory. In Java the freeing of memory is done when the object is no longer referenced.
  • Initialize the instance variables in the object
  • A constructor initializes the instance variables to their default values or in the case of a parameterized constructor, to the values passed in to the constructor.

Activity 8.3.6.

The following class defines a Fraction with the instance variables numerator and denominator. Complete the body of its 2 constructors. The no-argument constructor should set the default instance variable values to 1 rather than 0 since a fraction with 0 in the denominator is not valid. The constructor with parameters should copy those parameters into the instance variables. What will the code print out? Try tracing through it. View it in the Java visualizer by clicking on the Show CodeLens button below.

Activity 8.3.7.

The following class defines a Car with the instance variables model and year, for example a Honda 2010 car. However, some of the code is missing. First, fill in the code to create a Car constructor. Then, fill in the code to call the constructor in the main method to create 2 Car objects. The first car should be a 2023 Ford and the second car should be a 2010 Honda. Run your program and make sure it works and prints out the information for both cars.

Subsection 8.3.4 Coding Challenge: Student Class

We encourage you to work in pairs for this challenge to create a Student class with constructors.
  1. First, brainstorm in pairs to do the Object-Oriented Design for a Student class. What data should we store about Students? Come up with at least 4 different instance variables. What are the data types for the instance variables?
  2. Write a Student class below that has your 4 instance variables and write a constructor that has 4 parameters to set all of the instance variables.
  3. Add a print() method that uses System.out.println to print out all the instance variables.
  4. Add a main method that constructs at least 2 Student objects using the constructor with different values and then calls their print() methods.

Project 8.3.8.

Create a class Student with 4 instance variables, a constructor, and a print method. Write a main method that creates 2 Student objects with the constructor and calls their print() method.

Subsection 8.3.5 Design a Class for your Community

In the last lesson, you came up with a class of your own choice relevant to you or your community. In this lesson, you will add a constructor to this class.
  1. Consult your completed worksheet or your code in lesson 3.3 Community Challenge for the class name and its 3 instance variables that you created. Copy them into the active code exercise below.
  2. Add a constructor with 3 parameters to set all of the instance variables to the given parameters.
  3. Write a print() method that uses System.out.println to print out all the instance variables.
  4. Write a main method that constructs at least 2 objects of your class using the constructor and then calls their print() methods.

Project 8.3.9.

Copy your class with its 3 instance variables from lesson 3.3 Community Challenge. Add a constructor with 3 parameters to set all of the instance variables to the given parameters. Write a print() method that uses System.out.println to print out all the instance variables. Write a main method that constructs at least 2 objects of your class using the constructors and then calls their print() methods.

Subsection 8.3.6 Summary

  • (AP 1.13.A.1) A class contains constructors that are called with the keyword new to create objects and initialize its attributes.
  • (AP 1.13.A.1) Constructors have the same name as the class.
  • (AP 1.13.C.1) An object is typically created using the keyword new followed by a call to one of the class’s constructors. new ClassName() creates a new object of the specified class and calls a constructor.
  • (AP 1.13.B.1) The new object is saved in a variable of a reference type which holds an object reference or null if there is no object.
  • (AP 1.13.A.2) A constructor signature consists of the constructor’s name, which is the same as the class name, and the ordered list of parameter types.
  • (AP 1.13.A.2) The parameter list, in the header of a constructor, lists the types of the values that are passed and their variable names.
  • (AP 1.13.A.3) Constructors are said to be overloaded when there are multiple constructors with different signatures. They must differ in the number, type, or order of parameters.
  • A no-argument constructor is a constructor that doesn’t take any passed in values (arguments).
  • (AP 1.13.C.2) Parameters allow constructors to accept values to establish the initial values of the attributes of the object.
  • (AP 1.13.C.3) A constructor argument is a value that is passed into a constructor when the constructor is called. The arguments passed to a constructor must be compatible in order and number with the types identified in the parameter list in the constructor signature.
  • (AP 1.13.C.3) When calling constructors, arguments are passed using call by value. Call by value initializes the parameters with copies of the arguments.
  • (AP 1.13.C.4) A constructor call interrupts the sequential execution of statements, causing the program to first execute the statements in the constructor before continuing. Once the last statement in the constructor has been executed, the flow of control is returned to the point immediately following where the constructor was called.
  • (AP 3.4.A.1) An object’s state refers to its attributes and their values at a given time and is defined by instance variables belonging to the object. This defines a has-a relationship between the object and its instance variables.
  • (AP 3.4.A.2) A constructor is used to set the initial state of an object, which should include initial values for all instance variables. When a constructor is called, memory is allocated for the object and the associated object reference is returned. Constructor parameters, if specified, provide data to initialize instance variables.
  • A constructor must have the same name as the class! Constructors have no return type!
  • (AP 3.4.A.4) When no constructor is written, Java provides a no-parameter constructor, and the instance variables are set to default values according to the data type of the attribute. This constructor is called the default constructor. (Note that AP 3.4.A.3 is covered in lesson 3.6).
  • (3.4.A.5) Default values used by the default constructor:

Subsection 8.3.7 AP Practice

Activity 8.3.10.

Consider the following class. Which of the following successfully creates a new Cat object?
public class Cat
{
    private String color;
    private String breed;
    private boolean isHungry;

    public Cat()
    {
        color = "unknown";
        breed = "unknown";
        isHungry = false;
    }

    public Cat(String c, String b, boolean h)
    {
        color = c;
        breed = b;
        isHungry = h;
    }
}

I.   Cat a = new Cat();
II.  Cat b = new Cat("Shorthair", true);
III. String color = "orange";
     boolean hungry = false;
     Cat c = new Cat(color, "Tabby", hungry);
  • I only
  • I is one of the correct constructors but the second constructor can also be used.
  • I and II
  • II is not correct because there is no Cat constructor with 2 parameters.
  • I and III
  • I and III call the correct constructors.
  • I, II, and III
  • II is not correct because there is no Cat constructor with 2 parameters.
  • II and III
  • II is not correct because there is no Cat constructor with 2 parameters.

Activity 8.3.11.

Consider the following class. Which of the following code segments will construct a Movie object m with a title of β€œLion King” and rating of 8.0?
public class Movie {
    private String title;
    private String director;
    private double rating;
    private boolean inTheaters;

    public Movie(String t, String d, double r) {
        title = t;
        director = d;
        rating = r;
        inTheaters = false;
    }

    public Movie(String t) {
        title = t;
        director = "unknown";
        rating = 0.0;
        inTheaters = false;
    }
}
  • Movie m = new Movie(8.0, "Lion King");
  • There is no Movie constructor with 2 parameters.
  • Movie m = Movie("Lion King", 8.0);
  • There is no Movie constructor with 2 parameters.
  • Movie m = new Movie();
  • This creates a Movie object but it does not have the correct title and rating.
  • Movie m = new Movie("Lion King", "Disney", 8.0);
  • This creates a Movie object with the correct title and rating.
  • Movie m = new Movie("Lion King");
  • This creates a Movie object but it does not have a rating of 8.0.

Activity 8.3.12.

Consider the definition of the Cat class below. The class uses the instance variable isSenior to indicate whether a cat is old enough to be considered a senior cat or not.
public class Cat {
    private String name;
    private int age;
    private boolean isSenior;

    public Cat(String n, int a) {
        name = n;
        age = a;
        if (age >= 10) {
            isSenior = true;
        } else {
            isSenior = false;
        }
    }
}
Which of the following statements will create a Cat object that represents a cat that is considered a senior cat?
  • Cat c = new Cat (β€œOliver”, 7);
  • The age 7 is less than 10, so this cat would not be considered a senior cat.
  • Cat c = new Cat (β€œMax”, β€œ15”);
  • An integer should be passed in as the second parameter, not a string.
  • Cat c = new Cat (β€œSpots”, true);
  • An integer should be passed in as the second parameter, not a boolean.
  • Cat c = new Cat (β€œWhiskers”, 10);
  • Correct!
  • Cat c = new Cat (β€œBella”, isSenior);
  • An integer should be passed in as the second parameter and isSenior would be undefined outside of the class.

Activity 8.3.13.

Consider the following class definition. Each object of the class Cat will store the cat’s name as name, the cat’s age as age, and the number of kittens the cat has as kittens. Which of the following code segments, found in a class other than Cat, can be used to create a cat that is 5 years old with no kittens?
public class Cat
{
    private String name;
    private int age;
    private int kittens;

    public Cat(String n, int a, int k)
    {
        name = n;
        age = a;
        kittens = k;
    }
    public Cat(String n, int a)
    {
        name = n;
        age = a;
        kittens = 0;
    }
    /* Other methods not shown */
}

I.   Cat c = new Cat("Sprinkles", 5, 0);
II.  Cat c = new Cat("Lucy", 0, 5);
III. Cat c = new Cat("Luna", 5);
  • I only
  • Option III can also create a correct Cat instance.
  • II only
  • Option II will create a cat that is 0 years old with 5 kittens.
  • III only
  • Option I can also create a correct Cat instance.
  • I and III only
  • Good job!
  • I, II and III
  • Option II will create a cat that is 0 years old with 5 kittens.

Activity 8.3.14.

Consider the following class definition.
public class Cat {
    private String color;
    private boolean isHungry;
    /* missing constructor */
}
The following statement appears in a method in a class other than Cat. It is intended to create a new Cat object c with its attributes set to β€œblack” and true. Which of the following can be used to replace missing constructor code in the class definition so that the object c below is correctly created?
Cat c = new Cat("black", true);
  • public Cat(String c, boolean h)
    {
        c = "black";
        h = true;
    }
    
  • The constructor should be changing the instance variables, not the local variables.
  • public Cat(String c, boolean h)
    {
        c = "black";
        h = "true";
    }
    
  • The constructor should be changing the instance variables, not the local variables.
  • public Cat(String c, boolean h)
    {
        c = color;
        h = isHungry;
    }
    
  • The constructor should be changing the instance variables, not the local variables.
  • public Cat(String c, boolean h)
    {
        color = black;
        isHungry = true;
    }
    
  • The constructor should be using the local variables to set the instance variables.
  • public Cat(String c, boolean h)
    {
        color = c;
        isHungry = h;
    }
    
  • Correct!
You have attempted of activities on this page.