![]() | A nice way to handle errors in a Java Program. |
![]() | There are 5 keywords relating to the handling of exceptions: |
![]() |
try |
![]() |
catch |
![]() |
finally |
![]() |
throw |
![]() |
throws |
- Examine the following code sample:
![]() | Without proper initialization of the variables and and b, this code fragment will crash (divide by zero). |
![]() | It is possible to avoid the error with an if statement: |
![]() |
The code contained within the if statement is called protected code. I.e. If the code was not protected by the condition it may crash the program. |
![]() |
By protecting code with possible errors, crashes can be avoided. |
![]() |
The same protection as the above if statement can be done with try and catch exception handling: |
![]() |
When protecting code with condition statements the exact errors any particular code block may produce must be known. |
![]() |
By using try and catch, code can be protected without knowing the exact error. Thus it is easier to write this code than writing it using the "if". |
![]() |
When Java is about to crash it creates an exception. |
![]() |
Exceptions take the form of created objects. |
![]() |
After the Exception is created it is then thrown. If some element of the program is specified to catch the created exception object, then the exception will be intercepted by that element and the crash may be avoided. |
![]() |
All exceptions are eventually caught. If not caught by some element of programming, then they are “caught by the screen” and the program crashes. |
![]() |
Code specified to handle exceptions is contained within a catch block. |
![]() |
Each catch block must specify what exception it will handle. This is declared at the beginning of the block. I.e. catch( type of exception handled ){ |
![]() |
In the above code block, the e in the catch declaration is the name of the thrown (and caught) exception object. It can be any variable name, as it only reflects the name of the object in that specific block. |
![]() |
There are over 100 possible exceptions that could be thrown by Java. |
![]() |
It is possible to catch any possible thrown exception by
specifying the superclass of all exceptions Exception. I.e. catch(
Exception x ){ |
![]() |
While it is bad form to use only the Exception super class to cover all possible thrown exceptions, it is good form to use the Exception class to cover any possible over sights after specific exceptions have been handled. |
![]() |
When using multiple catch clauses, the first applicable catch block encountered will be the one applied, even if other catch clauses can be applied. |
![]() |
In general it is more common to use a method within a try block, rather than actually writing code there. I.e.,
|
![]() |
When using a method within a try block, the method should return the exception object, rather then crash. How do we do this? |
![]() |
There are two possible sources for methods: using an existing method from the Java API, or we write our own method. |
![]() |
In terms of methods from the API, if we examine the header of the method, we find something like this:
public static int divide(int a, int b) |
![]() |
The throws line always appears immediately after the header. The API will tell you that when this particular method is called, it is possible that it will throw an exception of the type defined by the throws clause at the header of the method. The API will normally document what exact conditions will cause the method to throw exceptions of these varying types. |
![]() |
Thus, when using such methods within a try block, you need to create catch blocks for all of the various exceptions the used method may throw. |
![]() |
This is easier then using created code because the guess work with exceptions is removed by the information in the API. |
![]() |
But what if the needed method is not in the API? (I.e., we have to create a method.) |
![]() |
|
![]() |
While some exceptions may make more sense when thrown than others, we are not restricted to certain types of exceptions when deciding which ones to throw. But remember to be reasonable in the types of exceptions thrown and when in doubt, throw a general Exception. |
![]() |
For our divide example, the code could look like this:
|
![]() |
To throw an error, we need to create an exception object. Thus the new ArithmeticException() in the throw statement. I.e., the exception object is created at the same time is it returned to the calling method in a throw. |
![]() |
Recall earlier we stated that try blocks were better than using condition error handling (if's) because the exact error does not need to be known when writing the code. But in the divide() method we just created, we use conditions to determine that an error exists. Can we write the same code without conditions? Yes. Here is the same method reformatted. |
![]() |
This performs the same as the previous method, but no condition was used to determine if an exception should be thrown! |
![]() |
When the return is tried, if b is 0, Java will generate its own ArithmeticException. We then catch the exception thrown by Java and re-throw it back to the calling method. However, we could change the type of exception thrown, we’re not obligated to throw the same type of exception as the one generated by Java. |
Writing your own exceptions
![]() |
Let’s say that you have written some code like this: try{ r1 = divide(a,b); r2 = multiply(a,b); } catch (ArithmeticException
e){… |
![]() |
When calling these two methods in the try block, it is possible that either will throw an ArithmeticException. But is it possible to tell which of the two methods produced the ArithmeticException in the catch block? |
![]() |
If we created the methods, we could just use differing exceptions for both methods and then just determine which produced the exception by the type thrown. |
![]() |
It is possible to hope for an exception class: public static int divide (int
a, int b) throws
DivideException{ if (b!=0) return
a/b; else throw new
DivideExcpetion(); } public static int multiply(int
a, int b) if (a = 1000 && b
<= 1000)
return a*b; else
throw new MultiplyException(); }
|
![]() |
public class DivideException
extends ArithmeticException{
public DivideException(){
super(); }
public DivideException( String s ){ super(
s ); } } public class
MultiplyException extends
ArithmeticException{
public MultiplyException (){
super(); }
public MultiplyException ( String s ){ super(
s ); } }
|
![]() |
It is of course possible to omit the two constructors defined in each of the above classes since if a class does not have any constructors explicitly written, then Java automatically provides the default constructor. We typically create our new exception by extending the closest matching existing exception class. In our case this was the ArithmeticException class.
|
Consider the following line of code:
int x = Integer.parseInt( “abc”);
Although this line would cause an exception (NumberFormatException) and although the API specifies that the method parseInt() throws a NumberFormatException, the compiler does not require that we protect this line inside a try block.
On the other hand, a line like of code like
read(…);
for calling method read() which throws IOException, that appears in several classes of the java.IO package cannot exist in a Java program without being protected inside a try-block, in the sense that the compiler would produce an error if we have this line unprotected.
![]() |
From the above discussion, we see that while for some methods that throw exceptions the compiler insists that we use a try-block to protect the methods’ calls, for other methods that also throw exceptions the compiler does not mind whether or not we protect those method calls. |
![]() |
It turns out that this is due to the fact that exceptions are classified as checked and unchecked. In the above examples, NumberFormatException belongs to the family of unchecked exceptions, whereas the exception IOException belongs to the family of checked exceptions. |
![]() |
In general, all subclasses of java.lang.Error and java.lang.RunTimeException are unchecked exceptions. This means that you do not have to write any exception handling code in order for your program to compile, when you invoke methods that throw these exceptions. On the other hand, all exceptions that are children of IOException but not of RuntimeException, are checked exceptions. The exceptions of type Exception are also checked exceptions. A checked exception is one for which the compiler checks to ensure that your code handles the exception that may be thrown. |