Exception Handling Java
Exception Handling Java
An exception is an abnormal condition that arises in a code sequence at run time. A Java
exception is an object that describes an exceptional condition that has occurred in a piece of
code. Java exception handling is managed via five keywords: try, catch, throw, throws, and
finally. Program statements that should be monitored for exceptions are contained within a
try block. catch block is used to handle the exceptions. To manually throw an exception, the
keyword throw is used . Any exception that is thrown out of a method must be specified by a
throws clause. Any code that absolutely must be executed after a try block completes is put
in a finally block.
try {
// block of code to monitor for errors
}
catch (ExceptionType1 exOb) {
// exception handler for ExceptionType1
}
catch (ExceptionType2 exOb) {
// exception handler for ExceptionType2
}
// ...
finally {
// block of code to be executed after try block ends
}
All exception types are subclasses of the built-in class Throwable. Immediately below
Throwable are two subclasses that partition exceptions into two distinct branches. One
branch is headed by Exception. This class should be sub classed to create user defined,
custom exception types. RuntimeException is an important subclass of Exception. It include
things such as division by zero and invalid array indexing.
The other branch is topped by Error, which defines exceptions that are not expected to be
caught under normal circumstances by the program. Exceptions of type Error are used by the
Java run-time system to indicate errors with respect to the run-time environment, itself. Stack
overflow is an example of such an error.
Uncaught Exceptions
Consider the code below:
class Exc0 {
public static void main(String args[]) {
int d = 0;
int a = 42 / d;
}
}
When the Java run-time system detects the attempt to divide by zero, it constructs a new
exception object and then throws this exception. This causes the execution of Exc0 to stop.
Since an exception handlers of our own is not written, the exception is caught by the default
handler provided by the Java run-time system. Any exception that is not caught by the
program will be processed by the default handler and causes termination of the program. The
default handler displays a string describing the exception and prints a stack trace from the
point at which the exception occurred. When the above code is executed the following is
displayed.
java.lang.ArithmeticException: / by zero
at Exc0.main(Exc0.java:4)
This program will cause a division-by-zero exception if it no command line arguments are
given. If a command line argument is given, then the value of a will be greater than zero and
hence no division-by-zero exception occurs. But it will cause an
ArrayIndexOutOfBoundsException, since the int array c has a length of 1, yet the program
attempts to assign a value to c[42].
Output:
When no command line argument is given:
a = 0
Divide by 0: java.lang.ArithmeticException: / by zero
After try/catch blocks.
When 1 command line argument is passed:
a = 1
Array index oob: java.lang.ArrayIndexOutOfBoundsException:42
After try/catch blocks.
try {
if(a==1) a = a/(a-a);
if(a==2) {
int c[] = { 1 };
c[42] = 99;
}
}
catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Array index out-of-bounds: " + e);
}
}
catch(ArithmeticException e) {
System.out.println("Divide by 0: " + e);
}
}
}
The program nests one try within another. When the program is executed with no command
line arguments, a divide by zero exception is generated by the outer try block. Execution of
the program with one command-line argument generates a divide-by-zero exception from
within the nested try block. Since the inner block does not catch this exception, it is passed
on to the outer try block, where it is handled. If the program is executed with two command-
line arguments an array boundary exception is generated from within the inner try block.
throw
To throw an exception explicitly, a throw statement is used. The general form of throw is
throw ThrowableInstance;
ThrowableInstance must be an object of type Throwable or a subclass of Throwable. There
are two ways to obtain a Throwable object:
creating one with the new operator.
using a parameter in a catch clause
The flow of execution stops immediately after the throw statement. Any subsequent
statements are not executed.
Example 1: (Creating with new operator)
public class MyClass {
static void checkAge(int age) {
if (age < 18) {
throw new ArithmeticException("Access denied - You must be at least 18
years old.");
} else {
System.out.println("Access granted - You are old enough!");
}
}
Output:
Exception in thread "main" java.lang.ArithmeticException: Access denied - You
must be at least 18 years old.
at MyClass.checkAge(MyClass.java:4)
at MyClass.main(MyClass.java:12)
Output
Caught in test
Caught in main
Rest of the code
throws
If a method is capable of causing an exception that it does not handle, it must specify this
behaviour so that callers of the method can guard themselves against that exception. This is
done by including a throws clause in the method’s declaration.
This is the general form of a method declaration that includes a throws clause:
type method-name(parameter-list) throws exception-list
{
// body of method
}
exception-list is a comma-separated list of the exceptions that a method can throw.
public class TestThrow1{
validate(13);
}
catch(ArithmeticException e)
{
System.out.println("Caught");
}
Output
Caught
rest of the code...
In the above code the method validate explicitly specifies that it will throw a Arithmetic
Exception and hence the caller of that method should take care to provide necessary
exception handling mechanism.
finally
Java finally block is a block that is used to execute important code such as closing
connection, stream etc. Java finally block is always executed whether exception is handled or
not. Java finally block follows try or catch block.
Finally block in java can be used to put "cleanup" code such as closing a file, closing
connection etc.
Case 1: No Exception occurs
class TestFinallyBlock{
public static void main(String args[]){
try{
int data=25/5;
System.out.println(data);
}
catch(NullPointerException e){System.out.println(e);}
finally{System.out.println("finally block is always executed");}
System.out.println("rest of the code...");
}
}
Output:
5
finally block is always executed
rest of the code...
Output:
Output:
Exception in thread main java.lang.ArithmeticException:/ by zero
finally block is always executed
rest of the code...
In all the above three case the finally block will be executed
Packages
Access Protection
The above table provides an illustration as to how members with different access specifiers
can be accessed.
Importing Packages
import statement is used to bring certain classes, or entire packages, into visibility. import
statements occur immediately following the package statement and before any class
definitions. The general form of import statement is:
import pkg1 [.pkg2].(classname | *);
Here, pkg1 is the name of a top-level package, and pkg2 is the name of a subordinate package
inside the outer package separated by a dot (.).Finally, anexplicit classname or a star (*) is
specified. * indicates that the Java compiler should import the entire package. java.lang is a
package that is implicitly imported by default by the compiler for all programs.
The import statement is optional. Any place if a user wants to use a class name, it can be
done with its fully qualified name, which includes its full package hierarchy. For example,
this fragment uses an import statement:
import java.util.*;
class MyDate extends Date {
}
The same example without the import statement looks like this:
class MyDate extends java.util.Date {
}
Example:
interface Test
{
int speed = 40;
void run();
}
Implementing Interfaces
Once an interface has been defined, one or more classes can implement that interface. To
implement an interface, the implements clause is included in a class definition, and then the
methods defined by the interface are created. If a class implements more than one interface,
the interfaces are separated with a comma. The methods that implement an interface must be
declared public. Also, the type signature of the implementing method must match exactly the
type signature specified in the interface definition.
class Example implements Test{
public void run()
{
System.out.println(“Run fast”);
}
}
The implementations can be accessed with interface references.
class Run
{
public static void main(String args[])
{
Test t = new Example();
t.run();
}
}
Output:
Run fast
Partial Implementations
If a class includes an interface but does not fully implement the methods defined by that
interface, then that class must be declared as abstract. For example:
interface Test
{
void play();
void run();
}
class Run{
public static void main(String args[])
{
A.Message m=new Test ();
m.msg();
}
}
Output: Hello nested interface
The interface message is addressed as A.message as it is nested within class A.
Practical example of an Interface
There are many ways to implement a stack. For example, a stack can be of a fixed size or it
can be “growable.” No matter how the stack is implemented, the interface to the stack
remains the same. That is, the methods push( ) and pop( ) define the interface to the stack,
independent of the details of the implementation.
In the example below two stack classes, FixedStack and DynamicStack are created have a
common Stack interface.
interface IntStack {
void push(int item); // store an item
int pop(); // retrieve an item
}
FixedStack(int size) {
stck = new int[size];
tos = -1;
}
else
return stck[tos--];
}
}
class DynStack implements IntStack {
int stck[];
int tos;
DynStack(int size) {
stck = new int[size];
tos = -1;
}
public void push(int item) {
if(tos==stck.length-1) {
int temp[] = new int[stck.length * 2]; // double size
for(int i=0; i<stck.length; i++) temp[i] = stck[i];
stck = temp;
stck[++tos] = item;
}
else
stck[++tos] = item;
}
class TestStack {
public static void main(String args[]) {
}
}
The size of the fixed stack is 5 and hence there will be “stack is full” message once the stack
is full but in the dynamic stack the size doubles each time the stack is full and hence no such
messages pop up.
Variables in an interface
The variables in an interface are by default public, static and final. A variable defined must be
assigned a value which cannot be changed by the implementing classes.
interface Moveable
{
int AVERAGE-SPEED = 40;
void move();
}
class Vehicle implements Moveable
{
public void move()
{
System .out. print in ("Average speed is"+AVERAGE-SPEED");
}
}
class Run {
public static void main (String[] arg)
{
Vehicle vc = new Vehicle();
vc.move();
vc. AVERAGE-SPEED = 60; // Error
}
}
Interfaces can be extended
One interface can inherit another by use of the keyword extends. The syntax is the same as
for inheriting classes. When a class implements an interface that inherits another interface, it
must provide implementations for all methods defined within the interface inheritance chain.
interface A {
void meth1();
void meth2();
}
interface B extends A {
void meth3();
}
class MyClass implements B {
class Run {
public static void main(String arg[]) {
Hierarchies can be built to contain as many layers as a user wants. Given three classes called
A, B, and C, C can be a subclass of B, which is a subclass of A. When this type of situation
occurs, each subclass inherits all of the traits found in all of its superclasses. In this case, C
inherits all aspects of B and A.
In the following example, a new subclass Shipment is created along with BoxWeight.
Shipment inherits all of the traits of BoxWeight and Box, and adds a field called cost, which
holds the cost of shipping.
class Box {
private double width;
private double height;
private double depth;
vol = shipment2.volume();
System.out.println("Volume of shipment2 is " + vol);
System.out.println("Weight of shipment2 is "
+ shipment2.weight);
System.out.println("Shipping cost: $" + shipment2.cost);
}
}
Because of inheritance, Shipment can make use of the previously defined classes of Box and
BoxWeight, adding only the extra information it needs for its own, specific application. This
is part of the value of inheritance; it allows the reuse of code. This example illustrates one
other important point: super( ) always refers to the constructor in the closest superclass. The
super( ) in Shipment calls the constructor in BoxWeight. The super( ) in BoxWeight calls
the constructor in Box. In a class hierarchy, if a superclass constructor requires parameters,
then all subclasses must pass those parameters “up the line.”
Method Overriding
In a class hierarchy, when a method in a subclass has the same name and type signature as a
method in its superclass, then the method in the subclass is said to override the method in the
superclass. When an overridden method is called from within a subclass, it will always refer
to the version of that method defined by the subclass. The version of the method defined by
the superclass will be hidden.
class A {
int i, j;
A(int a, int b) {
i = a;
j = b;
}
// display i and j
void show() {
System.out.println("i and j: " + i + " " + j);
}
}
class B extends A {
int k;
B(int a, int b, int c) {
super(a, b);
k = c;
}
// display k – this overrides show() in A
void show() {
System.out.println("k: " + k);
}
}
class Override {
public static void main(String args[]) {
B subOb = new B(1, 2, 3);
subOb.show(); // this calls show() in B
}
}
Output
k=3
When show( ) is invoked on an object of type B, the version of show( ) defined within B
is used. That is, the version of show( ) inside B overrides the version declared in A. If the
user wishes to access the superclass version of an overridden method, it can be done by
using super.
class B extends A {
int k;
B(int a, int b, int c) {
super(a, b);
k = c;
}
void show() {
super.show(); // this calls A's show()
System.out.println("k: " + k);
}
}
In this case the output would be
i and j: 1 2
k: 3
class Figure {
double dim1;
double dim2;
Figure(double a, double b) {
dim1 = a;
dim2 = b;
}
double area() {
System.out.println("Area for Figure is undefined.");
return 0;
}
}
class Rectangle extends Figure {
Rectangle(double a, double b) {
super(a, b);
}
// override area for rectangle
double area() {
System.out.println("Inside Area for Rectangle.");
return dim1 * dim2;
}
}
class Triangle extends Figure {
Triangle(double a, double b) {
super(a, b);
}
// override area for right triangle
double area() {
System.out.println("Inside Area for Triangle.");
return dim1 * dim2 / 2;
}
}
class FindAreas {
public static void main(String args[]) {
Figure f = new Figure(10, 10);
Rectangle r = new Rectangle(9, 5);
Triangle t = new Triangle(10, 8);
Figure figref;
figref = r;
System.out.println("Area is " + figref.area());
figref = t;
System.out.println("Area is " + figref.area());
figref = f;
System.out.println("Area is " + figref.area());
}
}
Output
Abstract classes
There are situations in which one would want to define a superclass that declares the structure
of a given abstraction without providing a complete implementation of every method.
Sometimes there will be a need to create a superclass that only defines a generalized form
that will be shared by all of its subclasses, leaving it to each subclass to fill in the details. In
such a condition a method is declared abstract in the base class. This method is overridden in
the subclass with the suitable implementation.
Any class that contains one or more abstract methods must also be declared abstract. To
declare a class abstract, the abstract keyword is used in front of the class keyword at the
beginning of the class declaration. There can be no objects of an abstract class. That is, an
abstract class cannot be directly instantiated with the new operator. Abstract constructors, or
abstract static methods cannot be defined. Any subclass of an abstract class must implement
all of the abstract methods in the superclass.
figref = t;
System.out.println("Area is " + figref.area());
}
}
It is now not possible to create an object of class Figure. But it is still possible to create a
reference variable.
To disallow a method from being overridden,specify final as a modifier at the start of its
declaration. Methods declared as final cannot be overridden. The following fragment
illustrates final:
class A {
final void meth() {
System.out.println("This is a final method.");
}
}
class B extends A {
void meth() { // ERROR! Can't override.
System.out.println("Illegal!");
}
}
Because meth( ) is declared as final, it cannot be overridden in B.
In order to prevent a class from being inherited, final keyword can be used. To do this,
precede the class declaration with final. Declaring a class as final implicitly declares all of its
methods as final, too.
final class A {
// ...
}
// The following class is illegal.
class B extends A { // ERROR! Can't subclass A
// ...
}
It is illegal for B to inherit A since A is declared as final.