Pinterest Stumbleupon Whatsapp
Advertisement

An Exception in programming signifies an exceptional condition at some point in the program execution. It is used when the exceptional condition can be handled better elsewhere rather than where it is encountered. Consider the following examples:

  • Failure to open a configuration file can be better handled higher up in the code, maybe by using an alternative configuration file location.
  • Accessing an array item How to Use a Java ArrayList How to Use a Java ArrayList A Java arraylist is a general-purpose resizeable array. It provides most of the facilities generally expected of arrays in other languages. In this article you'll learn to set up and use an arraylist. Read More outside the bounds of the array signifies a program bug. Happy debugging!
  • An XML parsing error should be brought to the notice of the user so the XML file can be corrected.
  • The program running out of memory (maybe when processing a large file) can be rectified by perhaps increasing the amount of memory available to the java process.

In all these cases (and more), the exception should be handled outside of the location where it is generated so the underlying cause can be addressed.

Types of Exceptions

The image below shows the main parts of the Java Exception Hierarchy. The base class is Throwable which is sub-classed into Exception and Error. Class Exception is for program related conditions that applications can catch in an attempt to salvage the situation. Class Error, on the other hand, is for indicating serious errors in the Java Run-time Environment which applications should not catch. Some examples are: OutOfMemoryError and StackOverflowError.

Exception Hierarchy

An Exception again is of two types: checked and unchecked. A checked exception must be handled by the calling code. This rule is enforced by the java compiler. An unchecked exception, on the other hand, can be propagated up the call chain without having to declare it explicitly. The examples below will clarify.

Checked Exceptions

The following method attempts to create FileReader from a file. The constructor throws a checked exception FileNotFoundException which must be handled by the calling code or declared to be thrown.

Advertisement

The following code will not compile since it does neither.

private void loadFile(String filename)
{
  FileReader in = new FileReader(filename);
}

One way to get the code to compile is to handle the exception (see below).

private void loadFile(String filename)
{
  try {
    FileReader in = new FileReader(filename)); {
  } catch(FileNotFoundException ex) {
    // handle exception here
  }
}

If the exception cannot be handled directly by the caller, it must be declared in the method signature.

private void loadFile(String filename) throws java.io.FileNotFoundException
{
  FileReader in = new FileReader(filename)); {
}

Unchecked Exceptions

An unchecked exception is one which is subclassed from RuntimeException and need not be handled directly or declared as above. For example, the following code results in a NullPointerException, which is a type of RuntimeException. The code, however compiles without error since NullPointerException is an unchecked exception.

private void handleEvent()
{
  String name = null;
  if ( name.length() > 0 ) {
  }
}

Wrapping Exceptions

Given the above discussion about checked and unchecked exceptions, it appears that it is easier to deal with unchecked exceptions since you don’t have to declare them or handle them yourself. With that convenience in mind, it may sometimes be useful to wrap a checked exception in an unchecked exception.

The following code example shown how to wrap an exception. The method method_1() throws an SQLException in its body. For the code to compile correctly, the exception must be declared to be thrown.

private void method_1() throws SQLException {
  ...
  throw new SQLException;
}

When this method is invoked from another method (method_2()), that method can catch the SQLException and wrap it inside an unchecked exception, so it does not have to declare the exception in its method signature.

private void method_2() {
  try {
    method_1();
  } catch(java.sql.SQLException ex) {
    throw new RuntimeException(ex);
  }
}

Exception Stack Trace

An Exception Stack Trace refers to the array of active stack frames, each of which represents a method invocation, captured by the JVM at the time the exception was thrown. Each stack frame includes the location of the method invocation including the class name, method name, and possibly the java source file name and line number within the file. It is useful for tracing back the sequence of calls that caused the error Java Exceptions: Are You Handling Them Right? Java Exceptions: Are You Handling Them Right? An Exception in programming signifies an exceptional condition in the program execution. It's used when the condition can be handled better elsewhere. Consider the following examples of Java exception handling. Read More .

Here is a typical stack trace, obtained from the exception object when it was caught.

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 8, Size: 5
  at java.util.ArrayList.rangeCheck(ArrayList.java:653)
  at java.util.ArrayList.get(ArrayList.java:429)
  at sample.sample1.main(sample1.java:24)

The exception caught here is IndexOutOfBoundsException. It includes additional information about the error. The stack trace contains 3 stack frames, each of which includes the location information as shown.

Handling Exceptions

An exception can be handled by catching it in a try-catch block and taking whatever corrective action is required. The Exception object provides several methods for extracting information about the condition which caused it.

The following code logs the error message to a log file.

private void loadConfig() {
  try {
    // invoke code which might generate an IOException
  } catch(java.io.IOException ex) {
    // handle exception here. May be log to a log file.
    log.warning(ex.getMessage());
  }
}

When an exception is wrapped inside another, you can retrieve the wrapped exception:

Throwable cause = ex.getCause();
log.warning("Underlying cause: " + cause.getMessage());

Do you need to access the stack trace, and maybe extract the name of the method that caused it?

StringBuilder sbuf = new StringBuilder("Stack Trace: ");
for (StackTraceElement el : ex.getStackTrace()) {
  sbuf.append(el.getClassName() + "." + el.getMethodName()).append("\n");
}
log.warning(sbuf.toString());

Or maybe, log the exception and rethrow it?

try {
  ...
} catch(java.io.IOException ex) {
  log.warning(ex.getMessage());
  throw ex;
}

The Exception class provides a printStackTrace() method which can print the stack trace to your own PrintStream (or PrintWriter).

try {
  ...
} catch(java.io.IOException ex) {
  PrintStream out = ...;
  out.println(ex.getMessage());
  ex.printStackTrace(out);
}

You can catch multiple types of exceptions in a single try block, and perform specific handling for each type of exception.

try {
  // throws some exceptions here
} catch(java.io.IOException ex) {
  // IOException specific handling here
} catch(java.sql.SQLException ex) {
  // SQLException specific handling here
}

To catch multiple exception types but use the same handling code, you can declare a catch block with multiple types as follows:

try {
  // throws some exceptions here
} catch(java.io.IOException | java.sql.SQLException ex) {
  // IOException and SQLException specific handling here
} catch(SAXException ex) {
  // SAXException specific handling here
}

Cleaning Up Resources With Finally

When dealing with code that can throw exceptions, it is essential to perform proper cleanup of any resources, such as opened files Everything You Need to Know About File Formats and Their Properties Everything You Need to Know About File Formats and Their Properties We use the word file interchangeably: music, image, spreadsheet, slideshow, and so on. But what makes a file a "file," anyway? Let's try and understand this fundamental part of computing. Read More , database connections, etc. Resource cleanup should be performed in a finally block. This way both normal exit and exceptional exit from a block invoke the cleanup code The 10 Worst Programming Mistakes in History The 10 Worst Programming Mistakes in History In its storied past, coding wrought destruction as well. Instances of a little bit of bad code caused disaster on a major level. The following are 10 of the worst programming mistakes in history. Read More .

InputStream in = null;
try {
  ...
  in = new FileInputStream(filename);
  ...
} catch(java.io.IOException ex) {
  log.warning(ex.getMessage());
} finally {
  // code here is executed on exiting the try block,
  // whether normally or due to an exception
  if ( in != null ) in.close();
}

Try-With-Resources Block

Java 1.7 introduced the try-with-resources construct which makes resource cleanup easier. It looks like this:

try( InputStream in = new FileInputStream(..) ) {
  // code which uses the InputStream.
}

When the code exits the block (whether cleanly or due to an exception), the InputStream variable is automatically cleaned up.

Cleanup multiple resources by declaring all of them in the block’s head.

try( InputStream in = new FileInputStream(..);
  Connection con = ...; ) {
  // code which uses the InputStream and the Connection.
}

Any object whose class implements the AutoCloseable interface can be cleaned up in this manner. The following class performs some specific cleanup in the close() method.

public class MyClass implements AutoCloseable {
  public void close() {
    // cleanup code here
  }
}

Use an instance of this class in a try-with-resources block.

try( MyClass obj = new MyClass(..) ) {
  // code which uses the MyClass object.
}

Some Commonly Encountered Exceptions

Let us now take a look at some commonly encountered exceptions.

  • IndexOutOfBoundsException (unchecked): indicates index of element being accessed is out of the bounds of an array, string, etc.
  • SQLException (checked): thrown due to a database error.
  • IOException (checked): file access error or errors having to do with input and output.
  • InterruptedException (checked): thrown when a thread execution is interrupted.
  • SAXException (checked): thrown due to XML parsing errors.
  • NullPointerException (unchecked): using null where an object is required.

Wrapping Up

Exceptions are the primary method for error reporting and management in Java. Proper use of exceptions enhance code quality Write or Code Faster in Your Linux Text Editor With Custom Themes Write or Code Faster in Your Linux Text Editor With Custom Themes Your Linux text editor doesn't have to look drab and "functional." Why not tweak it to enhance your productivity, whether scripting and coding or using the tool as a markup editor? Read More and help in resolving issues in production.

Do you have any exception-related war stories to relate? If so, tell us about it in the comments section below.

Image Credit: Dmitry Nikolaev via Shutterstock.com

Leave a Reply

Your email address will not be published. Required fields are marked *