Java Uncaught Exceptions <br />Before you learn to handle exceptions in a program, it is beneficial to see what happens if you don't handle them. The following applet includes an expression that deliberately causes a zero-divided error.
class Exc0 { public static void main(String args[]) { int d = 0; int a = 42 / d; }}
When the Java runtime system checks for the situation that is divided by zero, it constructs a new exception object and throws the exception. This causes the execution of Exc0 to stop, because once an exception is thrown, it must be caught by an exception handler and processed immediately. In this example, we do not provide any of our own exception handlers, so the exception is caught by the default handler of the Java runtime system. Any exception that is not caught by your program will eventually be handled by the default handler. The default handler displays a string describing the exception, prints the stack trace where the exception occurs, and terminates the program.
Here is the output generated by the standard javaJDK runtime interpreter to execute the program:
java.lang.ArithmeticException: / by zero at Exc0.main(Exc0.java:4)
Note how class name Exc0, method name main, file name Exc0.java and line number 4 are included in a simple stack usage track. Also, note that the thrown exception type is a subclass of Exception called ArithmeticException, which more clearly describes what type of error method. Discuss later in this chapter, Java provides multiple built-in exception types that match different types of runtime errors that may be generated.
The stack track will display the sequence of method calls that resulted in the error. For example, here is another version of the previous program that introduces the same error, but the error is generated in another method other than the main( ) method:
class Exc1 { static void subroutine() { int d = 0; int a = 10 / d; } public static void main(String args[]) { Exc1.subroutine(); }}
The stack track results of the default exception handler show how the entire call stack is displayed:
java.lang.ArithmeticException: / by zero at Exc1.subroutine(Exc1.java:4) at Exc1.main(Exc1.java:7)
As you can see, the bottom of the stack is line 7 of main, which calls the subroutine( ) method. This method causes an exception in line 4. The call stack is important for debugging because it pinpoints the exact steps that lead to the error.
Nesting of Java try statements
Try statements can be nested. That is, a try statement can be inside another try block. Every time you enter a try statement, the exception's before and after relationships will be pushed onto the stack. If an internal try statement does not contain a catch handler with special exceptions, the stack will pop up and the catch handler of the next try statement will check if it matches it. This process will continue until a catch statement matches successfully, or until all nested try statements are exhausted. If no catch statement matches, the Java runtime system will handle this exception. Here is an example of using nested try statements:
// An example of nested try statements.class NestTry { public static void main(String args[]) { try { int a = args.length; /* If no command-line args are present t, the following statement will generate a divide -by-zero exception. */ int b = 42 / a; System.out.println("a = " + a); try { // nested try block /* If one command-line arg is used,then a divide -by-zero exception will be generated by the following code. */ if(a==1) a = a/(aa); // division by zero /* If two command-line args are used,then generate an ou t -of-bounds exception. */ if(a==2) { int c[] = { 1 }; c[42] = 99; // generate an out-of-bounds exception } } catch(ArrayIndexOutOfBoundsExcept ion e) { System.out.println("Array index out-of-bounds: " + e); } } catch(ArithmeticException e) { System.out.println("Divide by 0: " + e); } }}
As you can see, the program nests another try block in one try block. The program works as follows: When you execute the program without command line parameters, the outside try block will generate an exception divided by zero. The program is executed under a command line parameter condition, and an error divided by a nested try block results in a divisible error. Because the inner block does not match this exception, it will pass the exception to the outer try block where the exception is processed. If you execute the program with two command line parameters, an array boundary exception is generated by the internal try block. The following results illustrate each case:
C:/>java NestTryDivide by 0: java.lang.ArithmeticException: / by zeroC:/>java NestTry Onea = 1Divide by 0: java.lang.ArithmeticException: / by zeroC :/> java NestTry One Twoa = 2Array index out- of-bounds: java.lang.ArrayIndexOutOfBoundsException
When there is a method call, the nesting of try statements can happen very secretly. For example, you can put a call to a method in a try block. Inside this method, there is another try statement. In this case, the try inside the method is still nested in the try block that calls the method externally. The following is a modification of the previous example, and the nested try blocks are moved to the inside of the method nesttry( ):
/* Try statements can be implicitly nested via calls to methods. */class MethNestTry { static void nesttry(int a) { try { // nested try block /* If one com mand-line arg is used,then a divide-by- zero exception will be generated by the following code. */ if(a==1) a = a/(aa); // division by zero /* If two command-line args are used,then generate an out-o f- bounds exception. */ if(a==2) { int c[] = { 1 }; c[42] = 99; // generate an out-of-bounds exception } } catch(ArrayIndexOutOfBoundsException e) { System.out .println("Array index out-of-bounds: " + e); } } public static void main(String args[]) { try { int a = args.length; /* If no command-line args are pre sent, the following statement will generate a divide-by-zero exception. */ int b = 42 / a; System.out.println("a = " + a); nesttry(a); } catch(ArithmeticExc episode e) { System. out.println("Divide by 0: " + e); } }}
The output of this program is the same as in the previous example.