Java
TOPIC i04 – ERROR HANDLING 1
LESSON NOTE
INTRO
Exceptions
are events that occur during program execution that interrupt the normal flow
of statements. For example, if you try
to open a file to that doesn’t exist, then the program cannot continue
normally.
In
this lesson, we will look at exceptions and how to handle them.
A FEW COMMON EXCEPTIONS
Here
are a few exceptions that you have likely seen:
- NullPointerException – Occurs when a
program uses a null object where an actual object is required.
- IndexOutOfBoundsException – Occurs when a
program tries to access an array’s element number that doesn’t exist.
- FileNotFoundException – Occurs when you try
to open a file that doesn’t exist in the specified location.
TWO FAMILES OF
EXCEPTIONS
There
are two groups of exceptions – checked exceptions and unchecked
exceptions.
Unchecked errors are runtime exceptions that are usually cannot be recovered
from as the code needs to be changed.
Examples include NullPointerException and IndexOutOfBoundsException. Such
exceptions do not need to be handled.
Checked
errors are exceptions that involve conditions outside of the program such as
missing files, lost network connections or invalid input. Such
exceptions must be handled. Any
method whose implementation can cause checked exceptions must handle the
exception.
All
you need to remember here is that some exceptions have to be handled and some
don’t.
HANDLING EXCEPTIONS
There
are two ways to handle exceptions:
1) using a try/catch statement,
or
2) having the method pass that
responsibility up the stack to the calling method.
TRY/CATCH STRUCTURE
The
try/catch structure allows us to catch exceptions and offer alternative code
that will be executed.
The
statement(s) that might cause the exception(s) are placed in the try
block. The statements that should be
executed when an exception occurs are placed in the catch block. Here is the general structure:
try
{
//statements that might cause an exception
go here
}
catch (TypeOfException e)
{
//statements that deal with exception go
here
}
EXAMPLE 1
In
the example below, the statement a[3]=4; creates
an exception. Normally, we would
simply get an error and the program would stop executing.
However,
using the try/catch, we can continue running the code. Immediately after
the exception, the statement inside the catch block is executed outputting
a message. If the statement in the
try was changed to be ‘legal’, then the statement in the catch block would
not be executed.
public static void
main(String[] args)
{
int[] a = {4,5,6};
try
{
a[3]=4;
//creates exception
}
catch(IndexOutOfBoundsException
e)
{
System.out.println("Max index number is 2");
}
}
Note: The exception
above does not need to be handled.
Therefore, we can run the program without the try/catch block and if
the exception occurs, then the program will simply stop running.
|
EXAMPLE 2
In
this example, we will work with file I/O.
Note that unlike example 1, we are forced to handle this type of
exception.
The
program below will simply open a file and output the content of its first
line to screen. Inside the try
block, three of the four statements can actually cause an exception.
public static void
main(String[] args)
{
BufferedReader
br = null;
try
{
br = new BufferedReader(new FileReader("file.txt"));
String firstLine = br.readLine();
System.out.println(firstLine);
br.close();
}
catch (Exception e)
{
System.out.println("Error
with file.");
}
}
Note: One issue here is
that it’s possible that you open a file, then cause an exception to jump to
the catch block and never close the file.
So it would be good to also close the file inside the catch block,
however, this would also require its own try/catch block.
|
MULTIPLE
CATCH BLOCKS
One can catch two different types of exceptions inside a single try block by simply using the
structure below:
try
{
//statements that might cause an exception
go here
}
catch (TypeOfException1 e)
{
//statements that deal with exception go
here
}
catch (TypeOfException2 e)
{
//statements that deal with exception go
here
}
THE FINALLY BLOCK
After
the try/catch block, you can also have a finally
block. The finally block contains statements that are executed
automatically whether the try
statement
created an exception or not.
At
first glance it might seem that the finally block
is useless. However, in the scenario
where the try/catch
blocks contain
return statements, the finally block can be used to run code
before the return is done.
The
common example is the scenario where a file is open and processed inside a try block. If a failure occurs, then we deal with that
in the catch block. However, either way, we need to close the
file so we put that code inside the finally block.
PASSING THE EXCEPTION UP
THE STACK
Alternatively
to dealing with the exception immediately, we can pass the exception handling
responsibility up the call stack. To
do this, in the method’s declaration, we simply use the following:
public static int
methodName() throws TypeOfException
By
doing the above, any method that calls methodName() will have to deal with the exception. Of course, that method can choose to use a
try/catch block or again pass that responsibility along up the stack.
EXAMPLE 1
The
File IO example from above can be written without a try/catch block if we
make the method containing it throw an Exception. Once passed above the main method(), the program will stop running.
public static void
main(String[] args) throws Exception
{
BufferedReader br = new BufferedReader(new FileReader("f.txt"));
String
firstLine = br.readLine();
System.out.println(firstLine);
br.close();
}
|
EXAMPLE 2
In
the example below, we have three methods.
The main method calls fun and fun calls superFun. The superFun
method can create an exception but instead of dealing with it there with a
try/catch, it sends that responsibility to the method that called it (fun
method). In turn, fun also sends
that responsibility to the method thatcalled it
(main method). The main method deals
with the exception using a try/catch structure.
public class PassingTheBuck
{
public static void
main(String[] args)
{
try
{
fun();
}
catch (Exception e)
{
System.out.println("There
were problems.");
}
}
public static void fun() throws Exception
{
superFun();
}
public static void superFun() throws Exception
{
BufferedReader
br = new BufferedReader(new FileReader("f.txt"));
String firstLine = br.readLine();
System.out.println(firstLine);
br.close();
}
}
|
|