We have seen the fundamentals of exception handling in our earlier sections. Exception handling in Java is implemented using Try/Catch blocks, in the examples mostly all the exceptions (Divide by zero, Array out of bounds exceptions) are thrown by the Java run time system. However, there would be some scenarios, where the statements are perfectly valid from Java run-time systems perspective, but the application would sill want to handle those scenarios as "exceptions".
Let us look at an example create such scenarios.
Here is the requirement from an application. The "result" cannot be greater than 200 in any case. If the result is greater that 200, application should raise an arithmetic exception.
public class exceptionHandlingExample { public static void main(String[] args) { int result = 0; int var1= 200; try { // Try Block -1 System.out.println(" Try Block-1: This statement is executed"); result = var1+10; if (result > 200) { throw new ArithmeticException(" Result above 200"); } // Any thing below this will not be executed. System.out.println(" This statement is not executed"); } catch(ArithmeticException e1) { System.out.println(" Try Block-1:Catch Block, Arithmetic Exception " + e1); result = 199; // Self correction, we may want to set result to 1. } catch (Exception e2) { System.out.println(" Try Block-1:Catch Block, Generic Exception"); } result = result + 1; System.out.println(" This is executed, Result: " + result); } }
From the above example, notice the usage of the key word "throw". As per the requirement, whenever the statement "result > 200" is true, new exception is triggered using the keyword "throw". This exception is treated just like any other runtime exceptions.
Notice, the two statements from the above example. First, "throw new ArithmeticException(" Result above 200");", It is possible to pass a parameter when an exception is thrown. In this example "Result above 200" is the msg sent. Second, "System.out.println(" Try Block-1:Catch Block, Arithmetic Exception " + e1);", notice the way the msg sent is being caught in the parameter "e1".
Compile/Run this program and here is the output:
Try Block-2: This statement is executed Try Block-2:Catch Block, Arithmetic Exception java.lang.ArithmeticException: Result above 200 This is executed, Result: 200
From the exception class hierarchy figure, exception class has 2 types (Runtime exceptions and IO exceptions) of subclasses under it. All the IO exceptions are called checked exceptions because compile throws an error if there are not handled. Runtime exception also called unchecked exceptions are handled by the compiler internally.
The compiler would not be happy with the below code snippet. Here is the reason for it, method1 throws an IOException and as we know IO Exceptions are checked exceptions and the compiler would complain if it is not handled.
// Notice the package to import. Eclipse will help you in adding the required packages. import java.io.IOException; public class exceptionHandlingThrowsExample { public static void method1() { System.out.println(" Inside method1"); // Compiler would not be happy with this statement because we do not // keep "throws IOException" after the method name. throw new IOException("Exception from method1") } public static void main(String[] args) { System.out.println(" Inside Main"); exceptionHandlingThrowsExample.method1(); } }
Unchecked exceptions are handled in 2 ways. First, using a try catch block. Second, using the keyword "Throws". Let use the keyword "throws" and modify the above code snippet. Notice the addition of keyword "throws" at the statement "public static void method1() throws IOException", this indicates any one calling the method "method1" would have to handle the IOException. Now, in the below example it is the duty of the main method to handle the exception!
import java.io.IOException; public class exceptionHandlingThrowsExample { // new code change to the above code snippet. public static void method1() throws IOException { System.out.println(" Inside method1"); // Compiler is now happy with this statement because we have added // the "throws IOException" after the method name. throw new IOException("Exception from method1"); } public static void main(String[] args) { System.out.println(" Inside Main"); // Compiler is now unhappy with the main() method since // it does not handle the "IOException". exceptionHandlingThrowsExample.method1(); } }
The compiler is still not happy with the above code snippet, addition of throws keyword to method one made sure that, it is the responsibility of the caller ( main method in this case) to handle the exception. The main method is not interested to handle it in this case, notice the code change made to the code snippet.
import java.io.IOException; public class exceptionHandlingThrowsExample { public static void method1() throws IOException { System.out.println(" Inside Method1"); // Compiler is now happy with this statement because we have added // the "throws IOException" after the method name. throw new IOException("Exception from Method1"); } public static void main(String[] args) throws IOException { System.out.println(" Inside Main"); // Compiler is now happy with this statement as well because we // have added the "throws IOException" after the method name too. exceptionHandlingThrowsExample.method1(); } }
Notice the addition of "throws" keyword at the end of main method. This means, main method is asking its caller to handle the exception. There is no one visible in this above code segment that calls the main method. Hence the compiler is happy now and ready to run the code.
Here is the output, there is no one to handle the exception and hence we see the stack trace in the output.
Inside Main Inside Method1 Exception in thread "main" java.io.IOException: Exception from Method1 at exceptionHandlingThrowsExample.method1(exceptionHandlingThrowsExample.java:7) at exceptionHandlingThrowsExample.main(exceptionHandlingThrowsExample.java:12)
We need to make one last modification to the code, to make the exceptions are handled and the application finishes execution gracefully. Here is the final version of the code snippet.
import java.io.IOException; public class exceptionHandlingThrowsExample { public static void method1() throws IOException { System.out.println(" Inside Method1"); throw new IOException("Exception from method1"); } public static void main(String[] args) { System.out.println(" Inside Main"); try { exceptionHandlingThrowsExample.method1(); } catch (IOException e) { System.out.println(" Exception has been Caught"); // If uncommented, the following statement will print the stack trace. //e.printStackTrace(); } } }
Compile/Run this program and here is the output:
Inside Main Inside Method1 Exception has been Caught