Choosing between Checked and Unchecked Exceptions

Here’s a flow chart for a quick reference. Detailed explanations below.

When is a situation “actually exceptional”?

An exceptional situation is an unexpected situation that is out of the ordinary. A situation is not exceptional just because it’s less common than other situations. In a non-exceptional situation you should use return values instead of exceptions.

For a detailed discussion with examples, see Return Values vs Exceptions.

Can the client recover from the situation?

If the client can’t reasonably be expected to recover from the situation, there’s no point in forcing it to catch the exception. In such unrecoverable situation an unchecked exception should be used.

Unrecoverable Examples Recoverable Examples
  • Misuse of the API
  • Internal error in the library
  • Unsupported operations
  • Network failures
  • USB-drive unplugged
  • Operation timed out

Is the situation predictable by the client?

If the client can predict or control the conditions under which a method throws an exception, then it’s capable of calling the method only when it knows that it will succeed. In such cases it’s wrong to force the client to wrap calls in try/catch blocks. That is, if the client can predict an exception, you should not use a checked exception (even if the situation is recoverable).

Example: PhoneNumber.parse(String input) returns a PhoneNumber, unless the input is malformed in which case it throws PhoneNumFormatException

The client can predict any exception since it controls the input to the method.

PhoneNumFormatException should therefore be unchecked.

(If a PhoneNumFormatException had been checked, the client would have been forced to include a catch block. This would have been nothing but annoying if the input to the method was a hardcoded valid phone number.)

Example: scanImage() uses a scanner to scan an image, or throws NoScannerException if no scanner is attached.

The client can not predict any exception, since the scanner can be unplugged at any time.

NoScannerException should be checked (since it's also reasonable to expect the client to recover).

Conclusions

Many conditions should be met for a checked exception to be a good fit. If you only use checked exceptions in truly exceptional situations where the outcome depends on the environment rather than the application state and the client can recover gracefully you should do fine. As always when designing an API, evaluate it by putting yourself in the shoes of the client and write some code against it.

Comments

Be the first to comment!