Exception TypesUncaught ExceptionsCustom Exception SubclassesUsing ‘try’ & ‘catch’Multiple ‘catch’ ClausesNested ‘try’ StatementsOther Exception KeywordsJava’s Built-in ExceptionsChained ExceptionsAdditional Exception Features
A Java exception is an object that describes an exceptional condition (an error) that occurs in a part of the code. The exception may be handled by the method itself or passed on when thrown. But in the end, the exception is caught and processed.
Exception Types
All exception classes are subclasses of a built-in class called
Throwable
. This has two distinct branches - Exception
and Error
. The Exception
branch further classifies known issues, such as division by zero or invalid array indexing (under RuntimeException
). (The
Error
subclass defines all conditions that aren’t expected to be caught under normal circumstances by the program.)Uncaught Exceptions
class Test { public static void main(String[] args) { int d = 0; int a = 42 / d; } } // the exception stack trace will include the class // name, the method name, and the line number.
java.lang.ArithmeticException: / by zero at Test.main(Test.java:4)
Custom Exception Subclasses
Creating custom exceptions can be done by subclassing the
Exception
class, which in turn is a subclass of the Throwable
that has its own overridable methods.class MyException extends Exception { private int detail; MyException(int a) { detail = a; } // method override. public String toString() { return "MyException[" + detail + "]"; } }
Using ‘try’ & ‘catch’
class Test { public static void main(String[] args) { try { int d = 0; int a = 42 / d; System.out.println("This will not be printed."); } catch (ArithmeticException e) { System.out.println("Division by zero."); } System.out.println("After catch statement."); } }
Division by zero. After catch statement.
Multiple ‘catch’ Clauses
class Test { public static void main(String[] args) { try { int a = args.length; System.out.println("a: " + a); int b = 42 / a; int c[] = { 1 }; c[42] = 99; } catch (ArithmeticException e) { System.out.println("Division by 0: " + e); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Array index OOB: " + e); } System.out.println("After try/catch blocks."); } }
Divide by 0: java.lang.ArithmeticException: / by zero After try/catch blocks. a = 1 Array index oob: java.lang.ArrayIndexOutOfBoundsException: Index 42 out of bounds for length 1 After try/catch blocks.
Nested ‘try’ Statements
class Test { public static void main(String[] args) { try { int a = args.length; int b = 42 / a; System.out.println("a: " + a); try { if (a == 1) a = a / (a - a); if (a == 2) { int c[] = { 1 }; c[42] = 99; } } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Array index OOB: " + e); } } catch (ArithmeticException e) { System.out.println("Division by 0: " + e); } } }
Other Exception Keywords
class KeywordsDemo { // throw: throw a ThrowableInstance. static void demoThrow() { try { throw new NullPointerException("demo"); } catch (NullPointerException e) { System.out.println("Caught inside 'demoThrow()'."); } } // throws: if a method causes an exception it does not // handle, it must specify this behaviour for its callers. static void demoThrows() throws IllegalAccessException { System.out.println("Inside 'demoThrows()'."); throw new IllegalAccessException("demo"); } // finally: a block of code executed after the try/catch // block is complete. static void demoFinally() { try { System.out.println("Have something here."); throw new RuntimeException(); } catch (RuntimeException e) { System.out.println("Here's the catch."); } finally { System.out.println("This will run at the end."); } } }
Java’s Built-in Exceptions
Unchecked exceptions are those that do not require a
throws
specification in the method. They are subclasses of RuntimeException
.Checked exceptions are the exceptions from
java.lang
that must be specified under throws
if not handled by the method itself.Chained Exceptions
These were introduced in Java in JDK 1.4 (yes, that old), and allow you to associate exceptions with each other. This helps the second exception describe the cause of the first exception. Two constructors were introduced for this feature.
// also been added to Error, Exception and RuntimeException Throwable(Throwable causeExc) Throwable(String msg, Throwable causeExc)
There’s also
getCause()
to get the underlying exception, and initCause()
which associates a new causeExc with the above layer.Additional Exception Features
From JDK 7, a couple of new features were introduced.
- Multi-catch: It allows two or more exceptions to be caught by the same clause, as
catch (ExceptionOne | ExceptionTwo e) { ... }
. Each multi-catch parameter is implicitly ‘final’.
- Precise rethrowing: This feature restricts the type of exceptions that can be rethrown to only those checked exceptions that the associated ‘try’ block throws, that are not associated with preceding ‘catch’ blocks.