Runtime errors can be divided into low-level
errors that involve violating constraints, such as:
- dereference
of a null pointer
- out-of-bounds
array access
- divide
by zero
- attempt
to open a non-existent file for reading
- bad
cast (e.g., casting an Object that is actually a Boolean to Integer)
and
higher-level, logical errors, such as violations of a function's precondition:
- call
to Stack's "pop" method for an empty stack
- call
to "factorial" function with a negative number
- call
to List's nextElement method when hasMoreElements is false
Logical
errors can lead to low-level errors if they are not detected. Often, it is
better to detect them (to provide better feedback).
- When
an error is detected, an exception is thrown. That is, the
code that caused the error stops executing immediately, and control is
transferred to the catch clause for that exception of the
first enclosing try blockthat has such a clause. The try block
might be in the current function (the one that caused the error), or it
might be in some function that called the current function (i.e., if the
current function is not prepared to handle the exception, it is
"passed up" the call chain). If no currently active function is
prepared to catch the exception, an error message is printed and the
program stops.
- Each
catch clause specifies the type of one exception, and provides a name for
it (similar to the way a function header specifies the type and name of a
parameter). Java exceptions are objects, so the statements in a catch
clause can refer to the thrown exception object using the specified name.
- The
finally clause is optional.
- In
general, there can be one or more catch clauses. If there is a
finally clause, there can be zero catch clauses
Question 1: Assume that function f might throw
exceptions Ex1, Ex2, or Ex3. Complete function g, outlined below, so that:
- If
the call to f causes Ex1 to be thrown, g will catch that exception and
print "Ex1 caught".
- If
the call to f causes Ex2 to be thrown, g will catch that exception, print
"Ex2 caught", and then will throw an Ex1
exception.
static void g() throws
... {
try {
f();
} catch ( ... ) {
...
} ...
}
Question 2: Consider the following function.
static void f(int k, int[] A, String S) {
int j = 1 / k;
int len = A.length + 1;
char c;
try {
c = S.charAt(0);
if (k == 10) j =
A[3];
} catch
(ArrayIndexOutOfBoundsException ex) {
System.out.println("array error");
throw new InternalError();
} catch
(ArithmeticException ex) {
System.out.println("arithmetic error");
} catch
(NullPointerException ex) {
System.out.println("null ptr");
} finally {
System.out.println("in finally clause");
}
System.out.println("after try block");
}
Part A.
Assume that variable X is an array of int that has been
initialized to be of length 3. For each of the following calls to function f,
say what (if anything) is printed by f, and what, if any, uncaught exceptions
are thrown by f.
A. f(0, X,
"hi");
B. f(10, X, "");
C. f(10, X, "bye");
D. f(10, X, null);
Part B.
Why doesn't f need to have a throws clause that lists the uncaught
exceptions that it might throw?
What is printed for each
of the four runs?
1. d caught Ex1
2. c caught Ex2
b caught Ex1
3. b caught Ex3
4. a caught Ex4
execution stops due to
uncaught exception Ex1 thrown in main
Question 1:
static void g() throws Ex1, Ex3 {
try {
f();
} catch (Ex1 ex1) {
System.out.println("Ex1
caught");
} catch (Ex2 ex2) {
System.out.println("Ex2
caught");
throw new Ex1();
}
}
Question 2:
Part A.
A. f(0, X, "hi");
nothing printed
throws ArithmeticException
B. f(10, X, "");
prints "in finally clause"
throws StringIndexOutOfBoundsException
C. f(10, X, "bye");
prints "array error", "in finally
clause"
throws InternalError
D. f(10, X, null);
prints "null ptr", "in finally clause",
"after try block"
Part B.
Function f doesn't need
to have a throws clause that lists the
uncaught exceptions that
it might throw because only uncaught CHECKED
exceptions need to be
listed in a function's throws clause.
The
uncaught exceptions that
f might throw are all UNCHECKED exceptions.
Declaring your own
Exception:
You can create your own
exceptions in Java. Keep the following points in mind when writing your own exception
classes:
·
All exceptions must be a
child of Throwable.
·
If you want to write a
checked exception that is automatically enforced by the Handle or Declare Rule,
you need to extend the Exception class.
·
If you want to write a
runtime exception, you need to extend the RuntimeException class.
We can define our own
Exception class as below:
class MyException extends Exception{
}
You just need to extend
the Exception class to create your own Exception class. These are considered to
be checked exceptions. The following InsufficientFundsException class is a
user-defined exception that extends the Exception class, making it a checked exception.
An exception class is like any other class, containing useful fields and
methods.
//
File Name InsufficientFundsException.java
import java.io.*;
public class InsufficientFundsException extends Exception
{
private double amount;
public InsufficientFundsException(double amount)
{
this.amount = amount;
}
public double getAmount()
{
return amount;
}
}
To demonstrate using our
user-defined exception, the following CheckingAccount class contains a
withdraw() method that throws an InsufficientFundsException.
//
File Name CheckingAccount.java
import java.io.*;
public class CheckingAccount
{
private double balance;
private int number;
public CheckingAccount(int number)
{
this.number = number;
}
public void deposit(double amount)
{
balance += amount;
}
public void withdraw(double amount) throws
InsufficientFundsException
{
if(amount <= balance)
{
balance -= amount;
}
else
{
double needs = amount - balance;
throw new InsufficientFundsException(needs);
}
}
public double getBalance()
{
return balance;
}
public int getNumber()
{
return number;
}
}
The following BankDemo
program demonstrates invoking the deposit() and withdraw() methods of
CheckingAccount.
// File Name
BankDemo.java
public class BankDemo
{
public static void main(String [] args)
{
CheckingAccount c = new CheckingAccount(101);
System.out.println("Depositing
$500...");
c.deposit(500.00);
try
{
System.out.println("\nWithdrawing
$100...");
c.withdraw(100.00);
System.out.println("\nWithdrawing
$600...");
c.withdraw(600.00);
}catch(InsufficientFundsException
e)
{
System.out.println("Sorry, but you
are short $"
+ e.getAmount());
e.printStackTrace();
}
}
}
Compile all the above
three files and run BankDemo, this would produce the following result:
Depositing $500...
Withdrawing $100...
Withdrawing $600...
Sorry, but you are short $200.0
InsufficientFundsException
at CheckingAccount.withdraw(CheckingAccount.java:25)
at BankDemo.main(BankDemo.java:13)
·
Exception can arise from different kind of
situations such as wrong data entered by user, hardware failure, network
connection failure, Database server down etc. In this section, we will learn
how exceptions are handled in java.
·