Java Exception Handling - Basics
Examples and Explanation of how to use Basic Exception Handling
*Note the examples are for explanation purposes only, and may not be the most efficient way to complete the problems/tasks set forward.
**These examples use the main method as to not over complicate the information, but this is applicable to any and all methods within a class.
Java will generate many exceptions during your time coding with this language. Some will be wanted, some will not be wanted, but they all must be dealt with to produce a good piece of programming code.
First of all,this tutorial will not help you determine the difference between the exceptions you know how to handle, and the ones you don't, but it will show you how to order them and group them, once you have made such a distinction in your program.
You have a few choices when you are confronted with an exception.
1) There is actually an error in your code, which needs to be fixed.
2) This is something which cannot be handled and needs to be dealt with.
3) This is something which cannot be handled and needs to be ignored.
numbers 2) and 3) are the more easy ones to deal with as it means your code is essentially correct, it is just possible to do something anyway which may generate an error.
*Side Note*
Many of these come from interfaces:
1) When multiple interfaces are implemented on a single object, or they inherit from each other. Sometimes the JVM has to make decisions, where you meant no code to run, some code is running.
2) If there are two or more types of objects and somehow an object of interface 1 is trying to be an object of interface 2. This can occur in both bad coding and intentional overlap, and handled by error checking.
*End Side Note*
Dealing with Existing Java Exceptions:
(Java.lang.Exception)
There is a large list of subclasses which each have there own subclasses of Exceptions, which Java is fully able to understand and give feedback on the reason for the triggering of the exception.
A classic example, i'm sure you have all run into is the
java.lang.ArrayIndexOutOfBoundsException, when you try to access an element passed the end of an array. This will be the first example of an exception to which we will handle.
Generates an unwanted Exception:
1 | public class exceptions{ |
2 | public static void main(String Args[]){ |
3 | int [] array = new int [ 3 ]; |
7 | System.out.println(array); |
so now we have an unwanted exception, perhaps what we really wanted to do was build a ciclic array, which points to first slot once we pass the end of the array.
For this simple task, we will use a
try catch block to trap the errors and send them to where we know how to handle them.
Simple Solution - The Try Catch Block:
01 | public class exceptions{ |
02 | public static void main(String Args[]){ |
03 | int [] array = new int [ 3 ]; |
08 | System.out.println(array); |
10 | catch (ArrayIndexOutOfBoundsException e){ |
12 | System.out.println( "Oops, we went to far, better go back to 0!" ); |
Now that the error is handled, we simply get a nice message telling us what happened, but the code
has not stopped it will continue until it reaches the end or another Exception. This is where you may modify variables that have exceeded their range, and other such problems created under the Exception heading.
*Notice that our line
System.out.println(array); gets skipped due to the exception. It is okay to place this line inside of the catch block, as it will not generate an exception of it's own (assuming array exists), but i will use this to demonstrate the addition of the
finally block.
In addition to the
Try and
catch blocks there is also the option to add
Finally. This is a block of code which should be free of exceptions in all circumstances as it will be run, no matter what!
If the try block completes without an Exception, the finally block excecutes.
If there is an Exception, once the catch block completes, the finally block excecutes.
This is where you get the program back on course after a possible exception, by calling your
update methods and reset variables that should be reset in all cases.
Simple Extension - Finally Block:
01 | public class exceptions{ |
02 | public static void main(String Args[]){ |
03 | int [] array = new int [ 3 ]; |
08 | System.out.println(array); |
10 | catch (ArrayIndexOutOfBoundsException e){ |
12 | System.out.println( "Oops, we went to far, better go back to 0!" ); |
15 | System.out.println(array); |
I realize that printing the array is not all that exciting, especially since it is just an address in memory, but it shows how the code continutes. Try changing the for loop to
i<3 and see how the Exception is not generated and that the array address is then printed twice! To correct this, simply remove the println from the try block and only the finally block will be printed each time.
Now that we can catch Exceptions, there are many additions to be found in java which will give more insight into where the Exception was generated.
All stack traces are from present location back to the source of the Exception
*items which are rarely used
fillInStackTrace:
-displays the excecution cylce of the stack trace.
getCause
-returns the cause of the Exception, in most cases this will be
null
getLocalizedMessage
-a description of why the Exception was thrown, usually not that informative without other information
getMessage
-the detailed description, usually exactly the same as getLocalizedMessage, but not always in a large program
getStackTrace
-displays memory address of trace points
*
initCause
-saves the cause of the exception to be passed or recreated
printStackTrace
-detailed list of all excecutions including line numbers, printed without
System.out
*
setStackTrace
-allows for modification of the trace points (beyond the scope of this tutorial)
toString
-string representation of the Exception, used when throwing (throwing seen in next tutorial)
How to use the above methods on an exception:
02 | public class exceptions{ |
03 | public static void main(String Args[]){ |
04 | int [] array = new int [ 3 ]; |
09 | System.out.println(array); |
11 | catch (ArrayIndexOutOfBoundsException e){ |
12 | System.out.println( "filIn: " + e.fillInStackTrace()); |
13 | System.out.println( "cause: " + e.getCause()); |
14 | System.out.println( "local: " + e.getLocalizedMessage()); |
15 | System.out.println( "messa: " + e.getMessage()); |
16 | System.out.println( "trace: " + e.getStackTrace()); |
19 | System.out.print( "trace: " ); e.printStackTrace(); |
21 | System.out.print( "string: " );e.toString(); |
25 | System.out.println( "Oops, we went to far, better go back to 0!" ); |
26 | throw (Exception) new Exception().initCause(e); |
29 | System.out.println(array); |
Output:
Quote
filIn: java.lang.ArrayIndexOutOfBoundsException: 3
cause: null
local: 3
messa: 3
trace: [Ljava.lang.StackTraceElement;@194df86
trace: java.lang.ArrayIndexOutOfBoundsException: 3
at exceptions.main(exceptions.java:12)
string:
Oops, we went to far, better go back to 0!
[I@defa1a
Exception in thread "main" java.lang.Exception
at exceptions.main(exceptions.java:26)
Caused by: java.lang.ArrayIndexOutOfBoundsException: 3
at exceptions.main(exceptions.java:12)
Press any key to continue...
*Notice that the exception is thrown at line 26, where we recreated the initCause and still points to the ArrayIndexOutOfBoundsException in the original cause.
Up to now we have dealt with a single Exception. What if there are multiple exceptions, but they all need to be handled differently?
Some things to keep in mind:
1) The class
Exception will catch all Exceptions no matter their source or cause.
2) Always handle Exceptions from the most specific and towards less specific.
3) It is a good idea to always make the last case in your catch block the Exception class to handle all unknown or unpredicted Exceptions.
Keeping with the same basic example, but i have removed all of the additional information and added a couple of new
problems that need to be dealt with.
The Base Code:
01 | public class exceptions{ |
02 | public static void main(String Args[]){ |
03 | int [] array = new int [ 3 ]; |
08 | System.out.println(array); |
*We have fixed the ArrayOutOfBoundsException, just in case let's leave that Catch option in.
Now we will add to this code. Since dividing by zero is an ArithmeticException, you can find this out by simply running the code above.
The end result is:
01 | public class exceptions{ |
02 | public static void main(String Args[]){ |
03 | int [] array = new int [ 3 ]; |
10 | catch (ArrayIndexOutOfBoundsException e){ |
11 | System.out.println( "Oops, we went to far, better go back to 0!" ); |
13 | catch (ArithmeticException e){ |
14 | System.out.println( "Cannot Divide by Zero!" ); |
18 | System.out.println( "An Unknown Error has Occured" ); |
22 | System.out.println(array); |
This time the ArrayIndexOutOfBoundsException is skipped, since the error generated was not of this type, but once it reached ArithmeticException, the category was correct and the code was executed. Catch blocks can be written in this order as many as are required.
To illustrate why the Exceptions are written in this order, run the following code which reverses ArithmeticException and Exception:
01 | public class exceptions{ |
02 | public static void main(String Args[]){ |
03 | int [] array = new int [ 3 ]; |
10 | catch (ArrayIndexOutOfBoundsException e){ |
11 | System.out.println( "Oops, we went to far, better go back to 0!" ); |
14 | System.out.println( "An Unknown Error has Occured" ); |
17 | catch (ArithmeticException e){ |
18 | System.out.println( "Cannot Divide by Zero!" ); |
22 | System.out.println(array); |
*If you have a good compiler, this should not compile at all!
Because ArithmeticException is a subclass of Exception, thus it can also handle the ArithmeticException, and becomes useless and will want to be thrown or caught, which cannot be done with Exception catching everything that comes it's way.
This also opens the door for grouping of errors, if you wish to treat all errors the same then only use Exception, or seperate by large subclasses. There is also the otherside where you could individualize each case, and even add some of your own (which will be talked about in another tutorial.