Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Exception Handling  ›  Capstone Project

Throwing Exceptions and Cleaning Up

Custom Exceptions 15 minA method throws an exception when it detects a problem it cannot fix, custom exceptions give such problems a precise name, and try-with-resources closes resources automatically.

Throwing Exceptions and Cleaning Up

So far we have caught exceptions that the library threw. Brew Bar's own rules need the same power: an order for 50 cups, or a drink that has run out, should stop the operation with a clear message. And the receipt printer must always be released, however the order ends.

The rule

Throw where it breaks, catch where you can fix it.

The method that discovers a problem is usually the wrong place to decide what to do about it. So it throws, and a caller higher up, such as the screen that can show a message, catches:

public void addCups(int extra) {
    if (extra < 1 || cups + extra > MAX_CUPS) {
        throw new IllegalArgumentException("cups must stay between 1 and " + MAX_CUPS);
    }
    cups += extra;
}

Keep the two keywords apart: throw (in the body) actually throws one exception object; throws (in the header) declares that a method might let one escape.

When no standard exception describes your situation, create your own by extending an existing class:

public class OutOfStockException extends Exception {
    public OutOfStockException(String drink) {
        super(drink + " is out of stock");
    }
}

Extend Exception for a checked exception, when callers should be forced to plan for it, as with running out of oat milk. Extend RuntimeException for an unchecked one, typically for misuse of your class. A named exception type lets callers catch exactly this problem and nothing else.

For clean-up, try-with-resources is better than a hand-written finally. Anything that implements AutoCloseable, such as files, network connections or Brew Bar's ReceiptPrinter, can be opened in brackets after try, and Java closes it automatically:

try (ReceiptPrinter printer = new ReceiptPrinter();
     CashDrawer drawer = new CashDrawer()) {
    printer.print(order.receipt());
    drawer.open();
}   // drawer closes, then printer, even if an exception was thrown

Resources are closed in reverse order of opening, like stacking and unstacking plates.

The shortcut

For every rule a method enforces, ask "Can this method fix it?" If yes, fix it there. If no, throw a well-named exception with a clear message and let the caller who can respond catch it. For anything that must be closed, reach for try-with-resources by default.

A customer orders a sold-out drinkStep 1 of 4
  1. Detect

    Kitchen.make("Oat latte") finds no oat milk. It cannot conjure milk, so it cannot fix this.

Drills

Answer fast — trust the rule.

quick drill

Which keyword appears in a method header to declare that an exception may escape?

quick drill

class MachineJammedException extends RuntimeException is thrown by a method with no throws clause. Does it compile?

quick drill

Each close method prints its class's initial, and nothing else prints except the body. What does try (Printer p = new Printer(); Drawer d = new Drawer()) { System.out.print("W"); } print?

quick drill

What can be opened in the brackets of a try-with-resources?

Remember

  • Throw where it breaks, catch where you can fix it.
  • throw throws one object; throws declares. Extend Exception for checked, RuntimeException for unchecked.
  • Use try-with-resources for anything closeable; it closes in reverse order.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainOut of oat milk

Design how Brew Bar's program should handle a drink that is out of stock. Explain where the exception is thrown and where it is caught, whether your custom exception should be checked or unchecked and why, and how you would make sure the receipt printer is always closed.