A small exception hierarchy with error codes
A custom exception is a class you write that extends Exception (checked) or RuntimeException (unchecked). It gives a failure a meaningful name, can carry extra data, and should keep the original exception as its cause.
Change the code and press Run (Ctrl+Enter). Try to predict the output first, then break it on purpose and read the error. Your edits are saved and match the lesson page.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Write an unchecked InvalidPinException with a field attemptsLeft. A method checkPin(String pin) accepts "1234" and otherwise throws it with the attempts left (start at 3). Try "0000", "1111" and "1234", printing what happens.
Write a checked ParseException-style class CsvException with a line field. A method int sumColumn(String[] lines) parses the second comma-separated value of each line and wraps any NumberFormatException with the line number (starting at 1) as the cause. Run it on {"a,1", "b,2", "c,x"}.
Write a method Throwable rootCause(Throwable t) that follows getCause() to the end. Test it on a three-level chain and print the root's class and message.
Explain it without notes
How do you decide whether a custom exception should extend Exception or RuntimeException?
What is exception chaining, and why is it important?
What constructors should a custom exception provide, and why?
When is a custom exception worth creating, and when should you use a standard one?
What is exception translation, and where do you do it?
Expected output
ordered tea
suggest something else: mango is out of stock
[PAYMENT_DECLINED] payment declined: card blocked