Java Arena
Step 4 of 5

One constructor calling another

The two constructors of CoffeeOrder in step 3 repeat each other: both store a drink and a size. That's only two lines, but setting up an object often takes more. Say the café adds a rule: it only has small, medium and large cups, and any other size is made a medium. With every constructor setting up the object on its own, a rule like that has to be written into each of them, and so does every instance variable the class gets later.

Instead, a constructor can hand the work to another constructor of the same class, with this(...):

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

    public CoffeeOrder(String drink, String size) {
        this.drink = drink;
        if (size.equals("small") || size.equals("large")) {
            this.size = size;
        } else {
            this.size = "medium";
        }
    }

    public CoffeeOrder(String drink) {
        this(drink, "medium");
    }

    public CoffeeOrder() {
        this("filter coffee");
    }

    public String toString() {
        return this.size + " " + this.drink;
    }
}
Output
large latte
medium tea
medium mocha
medium filter coffee
  • this(drink, "medium"); runs the constructor that takes two Strings, with the drink and the default size. That constructor sets up the object, and the one-parameter constructor has nothing else to do.
  • this("filter coffee"); runs the one-parameter constructor, which in turn runs the two-parameter one. However an order is made, it goes through the same code, so the size rule is written once.
  • Java picks the constructor for this(...) the same way as for new: by the values in the parentheses.

this(...) and this.size look alike but are different things. this.size is the object's instance variable. this with parentheses right after it runs another constructor on the same object, the one being built. It doesn't make a new object. Writing new CoffeeOrder(drink, "medium"); inside a constructor would build a second, separate order and throw it away, and the order being built would get no drink at all.

It must come first

this(...) can only be used in a constructor, and it must be the constructor's first statement. Anything before it is an error:

Main.java
public class Main {
    public static void main(String[] args) {
        CoffeeOrder order = new CoffeeOrder("latte");
    }
}
CoffeeOrder.java
public class CoffeeOrder {
    private String drink;
    private String size;

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

    public CoffeeOrder(String drink) {
        System.out.println("New order");
        this(drink, "medium");
    }
}
What javac prints
CoffeeOrder.java:12: error: call to this must be first statement in constructor
        this(drink, "medium");
            ^
1 error

After this(...), a constructor may do more: its other lines run once the other constructor has finished.

Your task

Challenge 1 of 3

Bouquet.java has a constructor that takes a kind of flower and a number of stems. Add a second constructor, Bouquet(String flower), for the florist's usual bouquet of 12 stems. Don't store the values in it: call the other constructor with this(...). The check runs:

Bouquet usual = new Bouquet("tulips");
Bouquet small = new Bouquet("roses", 5);
System.out.println(usual);
System.out.println(small);

and expects:

12 tulips
5 roses

Challenge 2

Here's the Snowman from step 3, with three constructors that each store both values. Rewrite the first two so that only Snowman(int balls, String nose) stores anything: Snowman(int balls) calls it with a carrot nose, and Snowman() calls one of the other constructors for 3 balls. The output stays the same:

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

Challenge 3

What does this program print? Each constructor of Lantern prints a line, so you can see when it runs. (Constructors don't usually print anything.)