Java Arena
Step 3 of 5

Several constructors

Some objects are nearly always made the same way. At a café, most coffee orders are for a medium cup, so writing "medium" in every order gets tiresome. A class can have more than one constructor, and new picks the one that fits:

Main.java
public class Main {
    public static void main(String[] args) {
        CoffeeOrder first = new CoffeeOrder("latte");
        CoffeeOrder second = new CoffeeOrder("mocha", "large");
        System.out.println(first);
        System.out.println(second);
    }
}
CoffeeOrder.java
public class CoffeeOrder {
    private String drink;
    private String size;

    public CoffeeOrder(String drink) {
        this.drink = drink;
        this.size = "medium";
    }

    public CoffeeOrder(String drink, String size) {
        this.drink = drink;
        this.size = size;
    }

    public String toString() {
        return this.size + " " + this.drink;
    }
}
Output
medium latte
large mocha
  • Both constructors have the class's name, but different parameters. Constructors like these are called overloaded constructors.
  • Java picks the constructor whose parameters fit the values in new. new CoffeeOrder("latte") gives one String, so it runs the first constructor. new CoffeeOrder("mocha", "large") gives two, so it runs the second. Values that fit no constructor, as in new CoffeeOrder(2), don't compile.
  • The first constructor fills in a default value: the size used when the order doesn't say one.

A constructor without parameters

Module 17 showed that Java adds a default constructor, without parameters, only to a class that has no constructor of its own. CoffeeOrder has two, so new CoffeeOrder() doesn't compile. If the café wants a quick way to order "the usual", the class needs a third constructor, written out:

public CoffeeOrder() {
    this.drink = "filter coffee";
    this.size = "medium";
}

A class can have as many constructors as it needs, in any order.

What makes constructors different

Constructors must differ in their parameter types: in the number of parameters, in their types, or in the order of the types. The parameter names don't count. Say the café wants a constructor for a drink and a kind of milk. It takes two Strings, just like the one for a drink and a size, so a call such as new CoffeeOrder("tea", "oat") couldn't say which one it meant. javac doesn't wait for such a call: it rejects the second constructor itself, even in a program that never uses it:

Main.java
public class Main {
    public static void main(String[] args) {
        System.out.println("The café is open");
    }
}
CoffeeOrder.java
public class CoffeeOrder {
    private String drink;
    private String size;
    private String milk;

    public CoffeeOrder(String drink, String size) {
        this.drink = drink;
        this.size = size;
        this.milk = "none";
    }

    public CoffeeOrder(String drink, String milk) {
        this.drink = drink;
        this.size = "medium";
        this.milk = milk;
    }
}
What javac prints
CoffeeOrder.java:12: error: constructor CoffeeOrder(String,String) is already defined in class CoffeeOrder
    public CoffeeOrder(String drink, String milk) {
           ^
1 error

CoffeeOrder(String,String) is the constructor as javac sees it: only the types, no names. A constructor for a drink, a size and a milk, CoffeeOrder(String drink, String size, String milk), would be fine, since it takes three values.

Your task

Challenge 1 of 3

A library loan is usually for 14 days. Loan.java has a constructor that takes the book's title and the number of days. Add a second constructor, Loan(String title), for a loan of 14 days. The check runs:

Loan usual = new Loan("Moby Dick");
Loan quick = new Loan("Atlas of Birds", 7);
System.out.println(usual);
System.out.println(quick);

and expects:

Moby Dick, due in 14 days
Atlas of Birds, due in 7 days

Challenge 2

A snowman has a number of snowballs and a nose. Write three constructors for the Snowman class:

  • Snowman() makes the classic snowman: 3 balls and a carrot nose.
  • Snowman(int balls) has that many balls, and a carrot nose.
  • Snowman(int balls, String nose) has the balls and the nose given.

The instance variables and toString are ready. The check prints new Snowman(), new Snowman(4) and new Snowman(2, "pine cone"):

3 balls, carrot nose
4 balls, carrot nose
2 balls, pine cone nose

Challenge 3

What does this program print? Label has three constructors. Look at the type of each value given to new.