Java: Return Values vs Exceptions

You should only use exceptions for exceptional situations. 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.

Exceptional Examples Non-exceptional Examples
  • An attempt to open a file failed
  • Computer ran out of memory
  • Program tried to divide by 0
  • Requested username already taken
  • A text string was entered in a numeric field
  • User does not have permission to change the data

Exceptional control flow is more complicated than ordinary if statements. In other words, by chosing exceptions for non-exceptional control flow you’re making the code more complicated than it needs to be.

Example: Instead of this…
try {
    foo();
    // then...
} catch (FooException ex) {
    // else...
}
…let foo() return true on success:
if (foo()) {
    // then...
} else {
    // else...
}
??

Or, if the return value of foo() is reserved for normal operation:

Example: Instead of this…
try {
    value = foo();
    // then...
} catch (FooException ex) {
    // else...
}
…let foo() return FooResult
FooResult result = foo();
if (result.success()) {
    value = result.getValue();
    // then...
} else {
    // else...
}
…or use a separate method
if (isFooAvailable()) {
    value = foo();
    // then...
} else {
    // else...
}
??
In the last two snippets, it's perfectly fine to let result.getValue() / foo() to throw an unchecked exception if result.success() / isFooAvailable() returns false.

If all you want to do is to skip the remaining part of a sequence of statements:

Example: Instead of this…
try {
    if (!initFoo()) throw AbortInit();
    // ...
    if (!initBar()) throw AbortInit();
    // ...
} catch (AbortInit e) {
}
…use a separate method…
void init() {
    if (!initFoo()) return;
    // ...
    if (!initBar()) return;
    // ...
}
…or use a labeled block and break:
init: {
    if (!initFoo()) break init;
    // ...
    if (!initBar()) break init;
    // ...
}

Comments