Java Exceptions Tutorial (part 1)
 

- JavaTouch

- Java SE Home
- Java Exceptions Home
- Java Exceptions- Best Pratices
- Java Exceptions Code Resources

 

Advantages of Exceptions

1. Separating Error-Handling Code from "Regular" Code
Exceptions provide the means to separate the details of what to do when something out of the ordinary happens from the main logic of a program. In traditional programming, error detection, reporting, and handling often lead to confusing spaghetti code.

2. Propagating Errors Up the Call Stack
 A second advantage of exceptions is the ability to propagate error reporting up the call stack of methods.
A method can duck any exceptions thrown within it, thereby allowing a method farther up the call stack to catch it. Hence, only the methods that care about errors have to worry about detecting errors.

method1 {
 try {
 call method2;
 } catch (exception e) {
 doErrorProcessing;
 }
}

method2 throws exception {
 call method3;
}

method3 throws exception {
 call readFile;
}

However, as the pseudocode shows, ducking an exception requires some effort on the part of the middleman methods. Any checked exceptions that can be thrown within a method must be specified in its throws clause.

3. Grouping and Differentiating Error Types

Because all exceptions thrown within a program are objects, the grouping or categorizing of exceptions is a natural outcome of the class hierarchy. An example of a group of related exception classes in the Java platform are those defined in java.ioIOException and its descendants. IOException is the most general and represents any type of error that can occur when performing I/O. Its descendants represent more specific errors. For example, FileNotFoundException means that a file could not be located on disk.

A method can write specific handlers that can handle a very specific exception. The FileNotFoundException class has no descendants, so the following handler can handle only one type of exception.

catch (FileNotFoundException e) {
 ...
}

A method can catch an exception based on its group or general type by specifying any of the exception's superclasses in the catch statement. For example, to catch all I/O exceptions, regardless of their specific type, an exception handler specifies an IOException argument.

catch (IOException e) {
 ...
}

This handler will be able to catch all I/O exceptions, including FileNotFoundException, EOFException, and so on.

Unchecked Exceptions — The Controversy:

 Because the Java programming language does not require methods to catch or to specify unchecked exceptions (RuntimeException, Error, and their subclasses), programmers may be tempted to write code that throws only unchecked exceptions or to make all their exception subclasses inherit from RuntimeException. Both of these shortcuts allow programmers to write code without bothering with compiler errors and without bothering to specify or to catch any exceptions. Although this may seem convenient to the programmer, it sidesteps the intent of the catch or specify requirement and can cause problems for others using your classes.
More..

 The Java programming language uses exceptions to handle errors and other exceptional events.

Definition:  An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.

When an error occurs within a method, the method creates an object and hands it off to the runtime system. The object, called an exception object, contains information about the error, including its type and the state of the program when the error occurred. Creating an exception object and handing it to the runtime system is called throwing an exception.

After a method throws an exception, the runtime system attempts to find something to handle it. The set of possible "somethings" to handle the exception is the ordered list of methods that had been called to get to the method where the error occurred. The list of methods is known as the call stack. 

 

The Three Kinds of Exceptions:

1. checked exception

These are exceptional conditions that a well-written application should anticipate and recover from.
eg: Suppose an application prompts a user for an input file name, then opens the file by passing the name to the constructor for java.io.FileReader. If the user supplies the name of a nonexistent file, and the constructor throws java.io.FileNotFoundException. A well-written program will catch this exception and notify the user of the mistake, possibly prompting for a corrected file name.
These exceptions are as much a part of that method's programming interface as its parameters and return value.
# Checked exceptions are subject to the Catch or Specify Requirement.


2 Error

These are exceptional conditions that are external to the application, and that the application usually cannot anticipate or recover from. For example, suppose that an application successfully opens a file for input, but is unable to read the file because of a hardware or system malfunction. The unsuccessful read will throw java.io.IOError. An application might choose to catch this exception, in order to notify the user of the problem — but it also might make sense for the program to print a stack trace and exit.
#Errors are not subject to the Catch or Specify Requirement.
# Errors are those exceptions indicated by Error and its subclasses.


3. Runtime exception

These are exceptional conditions that are internal to the application, and that the application usually cannot anticipate or recover from. These usually indicate programming bugs, such as logic errors or improper use of an API. For example, consider the application described previously that passes a file name to the constructor for FileReader. If a logic error causes a null to be passed to the constructor, the constructor will throw NullPointerException. The application can catch this exception, but it probably makes more sense to eliminate the bug that caused the exception to occur. 
Runtime exceptions can occur anywhere in a program, and in a typical one they can be very numerous. Having to add runtime exceptions in every method declaration would reduce a program's clarity. Thus, the compiler does not require that you catch or specify runtime exceptions (although you can).

# One case where it is common practice to throw a  RuntimeException is when the user calls a method incorrectly. For example, a method can check if one of its arguments is incorrectly null. If an argument is null, the method might throw a NullPointerException, which is an unchecked exception.
# Generally speaking, do not throw a RuntimeException or create a subclass of RuntimeException simply because you don't want to be bothered with specifying the exceptions your methods can throw.
#Runtime exceptions are not subject to the Catch or Specify Requirement.
# Runtime exceptions are those indicated by RuntimeException and its subclasses.

Note:
Errors and runtime exceptions are collectively known as unchecked exceptions


"Anyone who has never made a mistake has never tried anything new."

"The only reason for time is so that everything doesn't happen at once."

"When the solution is simple, God is answering."

- Albert Einstein

 

Catching and Handling Exceptions

The try Block

The first step in constructing an exception handler is to enclose the code that might throw an exception within a try block. In general, a try block looks like the following.

try {
 code
}
catch and finally blocks . . .

The segment in the example labeled code contains one or more legal lines of code that could throw an exception.
If an exception occurs within the try block, that exception is handled by an exception handler associated with it. To associate an exception handler with a try block, you must put a catch block after it.

The catch Blocks

You associate exception handlers with a try block by providing one or more catch blocks directly after the try block.
# No code can be between the end of the try block and the beginning of the first catch block.

try {
 
} catch (ExceptionType1 name) {
 
} catch (ExceptionType2 name) {
 
} 

Each catch block is an exception handler and handles the type of exception indicated by its argument. The argument type, ExceptionType, declares the type of exception that the handler can handle and must be the name of a class that inherits from the Throwable class. The handler can refer to the exception with name.

The catch block contains code that is executed if and when the exception handler is invoked. The runtime system invokes the exception handler when the handler is the first one in the call stack whose ExceptionType matches the type of the exception thrown. The system considers it a match if the thrown object can legally be assigned to the exception handler's argument

Eg1:

        try{
            FileInputStream file = new FileInputStream("test");
        }catch(FileNotFoundException e){
            // catch specific exception
            e.printStackTrace();
        }catch(IOException e){
            // catch more generic exceptions
            e.printStackTrace();
        }

 
The finally Block

The finally block always executes when the try block exits. This ensures that the finally block is always executed even if an unexpected exception occurs or not. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.

Important: The finally block is a key tool for preventing resource leaks. When closing a file or otherwise recovering resources, place the code in a finally block to insure that resource is always recovered.

eg:
The following finally block for the writeList method cleans up and then closes the PrintWriter.

finally {
 if (out != null) { 
 System.out.println("Closing PrintWriter");
 out.close(); 
 } else { 
 System.out.println("PrintWriter not open");
 } 
} 

 

Java Exceptions Language Rules and Design and Practices

Java Rule #1:
Valid Java programming language code must honor the Catch or Specify Requirement.. If a called method (or code block)  throws Exception(s), either you have to catch those Exceptios (or its super exceptions) or you must throw those Exceptions (or its super exception) from your method.
Code that fails to honor the Catch or Specify Requirement will not compile!

Example 1: Ctaching of Exceptions

java.lang.Object
   java.lang.Throwable
       java.lang.Exception
           java.io.IOException
               java.io.FileNotFoundException
 

import java.io.FileInputStream;
import java.io.FileNotFoundException; 

public class Test {
    public Test() {
    }

    public static void main(String[] args) {
        Test test = new Test();
        try{
            test.myMethod();  
        }catch(FileNotFoundException e){
            // In the catch block we should catch FileNotFoundException
            // or its super class. i.e IOException or Exception

            e.printStackTrace();
        }             
    }
   
    private void myMethod ()throws FileNotFoundException {      
        // Process Somthing relevent to file here
        FileInputStream file = new FileInputStream("test");
    }
}

Note:
Following code is also valid because IOException is supper class of FileNotFoundException.

        try{
            test.myMethod();  
        }catch(IOException e){
            e.printStackTrace();
        }

 

Example 2: Throwing of Exceptions
Say, we need to call FileInputStream constructor in our method call myMethod. FileInputStream throws exception called FileNotFoundException.

FileInputStream (API summary)
public FileInputStream(String name)
                throwsFileNotFoundException

So in our method we also need to throw the FileNotFoundException (assuming we are not handling the exception in our method itself).

    private void myMethod () throwsFileNotFoundException {      
        // Process Somthing relevent to file input stream here
        FileInputStream file = new FileInputStream("test.txt");
    }


Note:
Following code is also valid because IOException is supper class of FileNotFoundException.

    private void myMethod () throwsIOException {      
        // Process Somthing relevent to file input stream here
        FileInputStream file = new FileInputStream("test.txt");
    }

 

Design Practice # 1:
When you catch exception, you can have multiple catch blocks that catch the thrown exception as well as its sub exceptions. The advantage of catching specific sub exception seprately is that you can handle or report the specific exceptions differntly.

Example:

import java.io.*;

class FileStreamsTest {
    public static void main(String[] args) {
        try {
            File inputFile = new File("javatouchin.txt");
            File outputFile = new File("javatouchout.txt");

            // FileInputStream and FileOutputStream throws IOException 
            FileInputStream in = new FileInputStream(inputFile);
            FileOutputStream out = new FileOutputStream(outputFile);
            int c;
            while ((c = in.read()) != -1) {
               out.write(c);
            }
            in.close();
            out.close();
        } catch (FileNotFoundException e) {
            // Specific FileNotFoundException is catched and handle here
            System.err.println("FileStreamsTest: " + e);
        } catch (IOException e) {
            // generic IOException is catched here
            System.err.println("FileStreamsTest: " + e);
        }
    }
}

 

Java Rule #2:
The overriding method must not throw new or broader checked exceptions, than those declared by the overridden method.

Rate this Artical:

Current Rating: Rate This Artical: