Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking
In Java SE 7 and later, a single catch block can handle more than one type of exception. This feature can reduce code duplication and lessen the temptation to catch an overly broad exception.
Consider the following example, which contains duplicate code in each of the catch blocks:
catch (IOException ex) < logger.log(ex); throw ex; >catch (SQLException ex)
In releases prior to Java SE 7, it is difficult to create a common method to eliminate the duplicated code because the variable ex has different types.
The following example, which is valid in Java SE 7 and later, eliminates the duplicated code:
catch (IOException|SQLException ex)
The catch clause specifies the types of exceptions that the block can handle, and each exception type is separated with a vertical bar ( | ).
Note: If a catch block handles more than one exception type, then the catch parameter is implicitly final . In this example, the catch parameter ex is final and therefore you cannot assign any values to it within the catch block.
Bytecode generated by compiling a catch block that handles multiple exception types will be smaller (and thus superior) than compiling many catch blocks that handle only one exception type each. A catch block that handles multiple exception types creates no duplication in the bytecode generated by the compiler; the bytecode has no replication of exception handlers.
Rethrowing Exceptions with More Inclusive Type Checking
The Java SE 7 compiler performs more precise analysis of rethrown exceptions than earlier releases of Java SE. This enables you to specify more specific exception types in the throws clause of a method declaration.
Consider the following example:
static class FirstException extends Exception < >static class SecondException extends Exception < >public void rethrowException(String exceptionName) throws Exception < try < if (exceptionName.equals("First")) < throw new FirstException(); >else < throw new SecondException(); >> catch (Exception e) < throw e; >>
This examples’s try block could throw either FirstException or SecondException . Suppose you want to specify these exception types in the throws clause of the rethrowException method declaration. In releases prior to Java SE 7, you cannot do so. Because the exception parameter of the catch clause, e , is type Exception , and the catch block rethrows the exception parameter e , you can only specify the exception type Exception in the throws clause of the rethrowException method declaration.
However, in Java SE 7, you can specify the exception types FirstException and SecondException in the throws clause in the rethrowException method declaration. The Java SE 7 compiler can determine that the exception thrown by the statement throw e must have come from the try block, and the only exceptions thrown by the try block can be FirstException and SecondException . Even though the exception parameter of the catch clause, e , is type Exception , the compiler can determine that it is an instance of either FirstException or SecondException :
public void rethrowException(String exceptionName) throws FirstException, SecondException < try < // . >catch (Exception e) < throw e; >>
This analysis is disabled if the catch parameter is assigned to another value in the catch block. However, if the catch parameter is assigned to another value, you must specify the exception type Exception in the throws clause of the method declaration.
In detail, in Java SE 7 and later, when you declare one or more exception types in a catch clause, and rethrow the exception handled by this catch block, the compiler verifies that the type of the rethrown exception meets the following conditions:
- The try block is able to throw it.
- There are no other preceding catch blocks that can handle it.
- It is a subtype or supertype of one of the catch clause’s exception parameters.
The Java SE 7 compiler allows you to specify the exception types FirstException and SecondException in the throws clause in the rethrowException method declaration because you can rethrow an exception that is a supertype of any of the types declared in the throws .
In releases prior to Java SE 7, you cannot throw an exception that is a supertype of one of the catch clause’s exception parameters. A compiler from a release prior to Java SE 7 generates the error, «unreported exception Exception ; must be caught or declared to be thrown» at the statement throw e . The compiler checks if the type of the exception thrown is assignable to any of the types declared in the throws clause of the rethrowException method declaration. However, the type of the catch parameter e is Exception , which is a supertype, not a subtype, of FirstException and SecondException . catch parameter, and the exception handled by this catch block is not reassigned, then these exception types are implicitly final . You may explicitly declare these exception types as final ; however this is not necessary:
catch (final IOException|SQLException ex)
Exception types that are not final (in particular, catch blocks in which the handled exception is reassigned) affect the features discussed on this page as follows:
- The compiler generates an error for catch blocks that handles more than one exception type.
- The compiler will not perform the more inclusive type checking for rethrown exceptions.
The catch Blocks
You associate exception handlers with a try block by providing one or more catch blocks directly after the try block. No code can be between the end of the try block and the beginning of the first catch block.
try < >catch (ExceptionType name) < >catch (ExceptionType name)
Each catch block is an exception handler that handles the type of exception indicated by its argument. The argument type, ExceptionType , declares the type of exception that the handler can handle and must be the name of a class that inherits from the Throwable class. The handler can refer to the exception with name .
The catch block contains code that is executed if and when the exception handler is invoked. The runtime system invokes the exception handler when the handler is the first one in the call stack whose ExceptionType matches the type of the exception thrown. The system considers it a match if the thrown object can legally be assigned to the exception handler’s argument.
The following are two exception handlers for the writeList method:
try < >catch (IndexOutOfBoundsException e) < System.err.println("IndexOutOfBoundsException: " + e.getMessage()); >catch (IOException e)
Exception handlers can do more than just print error messages or halt the program. They can do error recovery, prompt the user to make a decision, or propagate the error up to a higher-level handler using chained exceptions, as described in the Chained Exceptions section.
Catching More Than One Type of Exception with One Exception Handler
In Java SE 7 and later, a single catch block can handle more than one type of exception. This feature can reduce code duplication and lessen the temptation to catch an overly broad exception.
In the catch clause, specify the types of exceptions that block can handle, and separate each exception type with a vertical bar ( | ):
catch (IOException|SQLException ex)
Note: If a catch block handles more than one exception type, then the catch parameter is implicitly final . In this example, the catch parameter ex is final and therefore you cannot assign any values to it within the catch block.
Catch All Exceptions in Java
How to catch all exceptions in Java? In Java, We can catch all exceptions with a single catch block using the “java.lang.Exception” parameter. We should use this catch block only for stopping abnormal terminations irrespective of the exception thrown from its corresponding try statement.
Note:- We can’t handle Error type exceptions either by using catch block or throws keyword. Example:- OutOfMemoryError, StackOverflowError, VirtualMachineError, NoClassDefFoundError and e.t.c. Because these types of exceptions are caused due to the lack of system resources. Errors are not recoverable. If OutOfMemoryError occurs, being a programmer we can’t do anything & the program will be terminated abnormally. System admin or server admin is responsible to increase heap memory.
Program to demonstrate how to catch all exceptions in Java
class Division < public static void main(String[] args) < try< int a = Integer.parseInt(args[0]); int b = Integer.parseInt(args[1]); int c = a/b; System.out.println("Result: " + c); >catch(Exception e) < System.out.println("Exception in the program"); >> >
Executing Division class without passing any value:- Since we are not passing any value therefore ArrayIndexOutOfBoundsException will be raised which will be handled by the catch block.
> java Division
Exception in the program
Executing Division class by passing string:- Inside program parseInt() is converting the passed value to integer number. If the passed value is a string then it will throw a NumberFormatException which will be handled by the catch block.
> java Division A
Exception in the program
Executing Division class by passing only one value:- We are calling args[1] but passed only one value therefore ArrayIndexOutOfBoundsException will be raised but handled by the catch block.
> java Division 10
Exception in the program
Executing Division class by passing only one integer value and one string:- The second value is not a number therefore NumberFormatException will be raised but handled by the catch block.
> java Division 10 a
Exception in the program
Passing only the second value as 0:- The second number is zero so, an ArithmeticException exception will occur.
> java Division 10 0
Exception in the program
Passing valid values to get the output message:-
> java Division 10 2
Result: 5
Based on the above all test-cases we can conclude that due to the “java.lang.Exception” parameter it can handle all exceptions, which was raised during the program execution. No need to write multiple catch blocks for different exceptions.
But we can also observe that there are some cons. Whenever an exception is raised, the catch block will be executed and for different wrong values, we are not able to figure out what is the problem in the program.
For example:- Our program gives the message “Exception in the program” when we pass the second number as a string (NumberFormatException), and it again gives the same output when the second number was zero (ArithmeticException). So we will not find the actual reason for the exception.
Hence, It is always recommended to write a catch block with an Exception parameter even though we are writing multiple catch blocks.
We must always define Exception parameter catch block in the below two situations,
- As a backup catch of all catch blocks, or
- To stop abnormal terminations irrespective of the exception raised in the program
Coding standards for handling exceptions:- We can use multiple catch blocks for handling known exceptions, but the last catch block should have a java.lang.Exception parameter which will be used to handle the unknown exception which may be raised in the program. The last catch block will be treated as a backup catch block, and program execution will be terminated normally.
Sample program to catch All Exceptions in Java
class Division < public static void main(String[] args) < try< int a = Integer.parseInt(args[0]); int b = Integer.parseInt(args[1]); int c = a/b; System.out.println("Result: " + c); >catch(ArrayIndexOutOfBoundsException aiobe) < System.out.println("Enter 2 integer values"); >catch(NumberFormatException nfe) < System.out.println("Passed value should be integer"); >catch(ArithmeticException ae) < System.out.println("2nd Number is 0, pass other value"); >catch(Exception e) < // for backup System.out.println("Exception in the program"); >> >
Output for the different input values:-
>java Division
Enter 2 integer values
>java Division A
Passed value should be integer
>java Division 10
Enter 2 integer values
>java Division 10 A
Passed value should be integer
>java Division 10 0
2nd Number is 0, pass other value
>java Division 10 2
Result: 5
If you enjoyed this post, share it with your friends. Do you want to share more information about the topic discussed above or do you find anything incorrect? Let us know in the comments. Thank you!