Home > Back-end >  Why don't methods need to return a value after throwing an exception?
Why don't methods need to return a value after throwing an exception?

Time:12-10

This is a contrived example. I have a non-void method and it throws an exception. Why don't I have to return a value afterwards? After all, the method is non-void.

public static Toast makeText(Context context, CharSequence text, int duration) {
    throw new RuntimeException("Stub!");
    //Must return something from here but there is not, Why?
}

CodePudding user response:

Throwing an exception interrupts the flow of control, exiting from the method immediately. When an exception is thrown, no return value is needed because the code which called the method does not complete normally. For example, in the following code, there is no need for foo to return a number, because int x = foo(); doesn't succeed, it instead propagates the exception:

int foo() {
    throw new RuntimeException();
}
void bar() {
    int x = foo();
    // This line will not be reached
    System.out.println(x);
}

Since the code after int x = foo(); won't be executed anyway, there is no need for x to receive a return value from foo, and therefore foo doesn't need to provide a return value.

In fact, a method cannot both return a value and also throw an exception, since returning a value would mean the method completes normally.

CodePudding user response:

There is no actual requirement for a method returning a value to contain a return statement. Perhaps surprisingly, this code is legal:

int noReturn() {
  while (true) {}
}

The key big of the language spec is JLS 8.4.7, which says:

If a method is declared to have a return type (§8.4.5), then a compile-time error occurs if the body of the method can complete normally (§14.1).

"Normal completion" is described in JLS 14.1:

Every statement has a normal mode of execution in which certain computational steps are carried out. The following sections describe the normal mode of execution for each kind of statement.

If all the steps are carried out as described, with no indication of abrupt completion, the statement is said to complete normally. However, certain events may prevent a statement from completing normally:

  • The break, yield, continue, and return statements (§14.15, §14.21, §14.16, §14.17) cause a transfer of control that may prevent normal completion of expressions, statements, and blocks that contain them.
  • Evaluation of certain expressions may throw exceptions from the Java Virtual Machine (§15.6). An explicit throw (§14.18) statement also results in an exception. An exception causes a transfer of control that may prevent normal completion of statements.

So: the requirement is that the method must not complete normally; and both return and throw are ways of causing the method to complete abnormally.


Note that this doesn't say that the method must complete abnormally instead: returning to the while loop example at the start, that doesn't complete normally or abnormally: because the loop condition is a constant true, and doesn't contain a return, throw or break, or a statement that might throw an exception, that loop never completes, which is also fine (at least from the language perspective).

  • Related