1 Predict the Output
Read each code snippet carefully. Trace the execution flow through try, catch, and finally blocks. Predict what gets printed — and what does NOT get printed. Then reveal the answer to check your understanding.
Explanation: "A" prints first. Then 10 / 0 throws ArithmeticException. "B" is never reached because the exception occurs on the line before it. The catch block matches, so "C" prints. After the try-catch, execution continues normally and "D" prints.
Explanation: "A" prints. Then arr[5] throws ArrayIndexOutOfBoundsException. The catch block only handles ArithmeticException — it does NOT match. "C" is skipped. The finally block always runs, so "D" prints. Then the unhandled exception propagates and the program crashes. "E" is NOT printed.
Explanation: "A" prints. Then s.length() throws NullPointerException. "B" is skipped. The first catch matches NullPointerException, so "C" prints. The second catch (Exception) is skipped because the exception was already handled. finally always runs, so "E" prints. The program continues normally and "F" prints.
Explanation: method2() throws ArithmeticException. In method1(), the catch block handles NullPointerException — that does NOT match. "D", "E", and "F" are all skipped as the exception propagates out of method1(). Back in main(), the catch block handles Exception — which IS a parent of ArithmeticException, so it matches. "B" prints. "A" is skipped. After the try-catch, "C" prints.
2 Fix the Error
Each of the following code snippets contains a compilation error related to exception handling. Identify the problem and figure out how to fix it before revealing the solution.
Problem: new File("data.txt") passed to Scanner can throw FileNotFoundException, which is a checked exception. The compiler forces you to handle it.
Fix Option 1: Wrap in try-catch:
Fix Option 2: Add throws to main:
Problem: Exception is the parent of ArithmeticException. The first catch block catches everything, making the second catch block unreachable. Java does not allow unreachable catch blocks.
Fix: Put the more specific exception FIRST:
Problem: Inside the method body, you use throw (no 's') to actually throw an exception object. The keyword throws (with 's') is only used in the method signature to declare what exceptions a method might throw.
Fix: Change throws to throw inside the if block:
throws = declaration (declare in the method signature what exceptions it might throw)
3 Write Your Own
Now it's your turn to write code from scratch. These exercises require you to create custom exception classes and use them properly. Try to write the full solution before looking at any references.
Exercise 1 Custom Checked Exception — InvalidGradeException
- Create a custom checked exception called InvalidGradeException that extends Exception.
- Write a Student class with a setGrade(double grade) method.
- The setGrade method should throw InvalidGradeException if the grade is less than 0 or greater than 100.
- Write a main method that creates a Student object, calls setGrade with both valid and invalid values, and handles the exception with a try-catch block.
- Your exception class needs a constructor that takes a String message and passes it to super(message).
- Since it is a checked exception, the setGrade method must declare throws InvalidGradeException.
- The caller must either catch or re-throw.
Exercise 2 Custom Unchecked Exception — EmptyStackException
- Create a custom unchecked exception called EmptyStackException that extends RuntimeException.
- Write a simple Stack class that uses an array internally with push(int value) and pop() methods.
- The pop method should throw EmptyStackException if the stack is empty.
- Write a main method that pushes a few values, pops them all, and then tries to pop one more time to trigger the exception.
- Since it extends RuntimeException, the pop method does NOT need to declare throws.
- Use a top variable (initialized to -1) to track the top index of the stack.
- In pop(), check if (top == -1) and throw your exception.
4 Code Tracing
This is the toughest challenge. Multiple methods, nested try-finally blocks, and exception propagation all in one. Trace through carefully, step by step.
Step-by-step trace:
- main() enters try block. Prints "1".
- main() calls a().
- a() enters its try block. Prints "6".
- a() calls b().
- b() throws Exception.
- Back in a() — "7" is skipped. There is no catch block in a(), but the finally block runs. Prints "8".
- The exception propagates out of a() back to main().
- In main(), "2" is skipped. The catch block matches Exception. Prints "3".
- main()'s finally block runs. Prints "4".
- Execution continues after the try-catch-finally. Prints "5".