You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 61 Next »

Exceptions should be used only to denote exceptional conditions. They should not be used for ordinary control flow purposes, for several reasons. First, catching an exception is likely to catch unexpected errors; see  ERR08-J. Do not catch NullPointerException or any of its ancestors for examples. When a program catches a specific type of exception, it does not know exactly where that exception was thrown. Using a catch clause to handle an exception that occurs in a known location is a poor solution; it is preferable to handle the error as soon as it occurs, or prevent it, if possible. The non-locality of throw statements and corresponding catch statements can also impede optimizers from improving code that relies on exception handling. Catching exceptions also complicates debugging, as they indicate a jump in control flow from the throw statement to the catch clause. Finally, exceptions need not be implemented to perform optimally, as it is assumed they are only thrown upon exceptional circumstances. Throwing and catching an exception will often yield slower code than handling the error with some other mechanism.

Noncompliant Code Example

This noncompliant code example attempts to concatenate the processed elements of the strings array:

public String processString(String string) {
  // ...
  return string;
}
public String processStrings(String[] strings) {
  String result = "";
  int i = 0;
  try {
    while (true) {      
      result = result.concat( processString( strings[i]));
      i++;
    }
  } catch (ArrayIndexOutOfBoundsException e) {
    // Ignore, we're done
  }
  return result;
}

It uses an ArrayIndexOutOfBoundsException to detect the end of the array. Unfortunately since ArrayIndexOutOfBoundsException is a RuntimeException, it could be thrown by processString() without being declared in a throws clause. So it is possible for processStrings() to terminate before all of the strings are processed.

Compliant Solution

This compliant solution uses a standard for loop to concatenate the strings. In this case the ArrayIndexOutOfBoundsException can only occur under some exceptional circumstances, and can be handled outside of normal processing.

public String processStrings(String[] strings) {
  String result = "";
  try {
    for (int i = 0; i < strings.length; i++) {
      result = result.concat( processString( strings[i]));
    }
  } catch (ArrayIndexOutOfBoundsException e) {
    // handle error
  }
  return result;
}

Technically this code need not catch ArrayIndexOutOfBoundsException since it is a runtime exception.

Applicability

Use of exceptions for any purpose other than detecting and handling exceptional conditions complicates program analysis and debugging, degrades performance and can increase maintenance costs.

Bibliography

[Bloch 2001]Item 39, "Use Exceptions Only for Exceptional Conditions"
[JLS 2011]Chapter 11, "Exceptions"

 


  • No labels