11

I have a method that handles different error codes and always throws unchecked exception. This method is used in many places across the class. When I try to call it inside another method that has not void return type as shown below:

public Object someMethod() {
   ....
   if(success){
     return result;
   } else {
      callMethodThatAlwaysThrowsUncheckedExceptions();
   }
}

java compiler says that the method is missing return statement.

Only two options come to my mind how to solve this problem:

  • replace method call with its content
  • add a return statement just after method call that returns an empty object

However I don't really like any of these options: the first one because of code duplication and the second one because of the need to write code that will never be executed.

Is there any other way to solve this problem?

Ermiya Eskandary
  • 15,323
  • 3
  • 31
  • 44
eparvan
  • 1,639
  • 1
  • 15
  • 26

5 Answers5

13

Just swap around the terms, you'll never get to return if the method throws.

 if(!success){
   callMethodThatAlwaysThrowsUncheckedExceptions();
 } 

 return result;

Or even

 callMethodThatAlwaysThrowsUncheckedExceptions(succes);
 return result;

Just check the success condition in your throwing method.

minus
  • 2,646
  • 15
  • 18
9

Next to the great answer already provided by Slawomir Chodnicki, here's another suggestion.

Change your callMethodThatAlwaysThrowsUncheckedExceptions() which somewhere throws an Exception into a factory method. E.g: change this:

// somewhere in callMethodThatAlwaysThrowsUncheckedExceptions
throw new MyException();

To:

return new MyException();

That way you can call that method like this:

throw callMethodThatAlwaysThrowsUncheckedExceptions();

And thus will help the compiler to see that this is the last statement of that execution branch.

This also works greatly with different exceptions, just return instead of throw

Lino
  • 19,604
  • 6
  • 47
  • 65
  • 1
    Even better: that other method can still **throw** instead of return ... just to be really really sure that exception gets thrown always! I call that the "double throw up" pattern. – GhostCat May 29 '19 at 12:35
  • @GhostCat I have to say that it's rather confusing, but it doesn't really make a difference. though, the stacktrace could maybe be different, have to check that. **Edit** it is not different, as it's created when the constructor is called – Lino May 29 '19 at 12:37
  • 1
    Well, as long as the method name is really telling, it doesnt matter to much. – GhostCat May 29 '19 at 12:54
5

To indicate that you don't expect a line to be reachable (after your call to the throwing method) you can

throw new AssertionError("comment to your co-developers why this never gets reached")

Slawomir Chodnicki
  • 1,525
  • 11
  • 16
2

I like minus's answer, but it can be a bit unreadable to users that might mistakenly think return result; will always be executed (regardless of the value of success).

As an alternative, you can change

void callMethodThatAlwaysThrowsUncheckedExceptions () {}

to

Object callMethodThatAlwaysThrowsUncheckedExceptions () {}

(no need to change the method body).

Now you can write

public Object someMethod() {
    ....
    if (success) {
        return result;
    } else {
        return callMethodThatAlwaysThrowsUncheckedExceptions();
    }
}
Eran
  • 387,369
  • 54
  • 702
  • 768
0

None of the answers above matched my taste of programming. The closest match that I found is here. Inspired from this linked answer, I handled such missing return statement errors in the following way:

First making the return type of the method same as that of exception which it always throws

MyCustomRuntimeException callMethodThatAlwaysThrowsUncheckedExceptions() {
    // ....
    throw new MyCustomRuntimeException();
}

Next whenever we have to fail the method execution, simply call above method and throw it

public Object someMethod() {
   // ....
   if (success) {
     return result;
   } else {
      throw callMethodThatAlwaysThrowsUncheckedExceptions();
   }
}

This can be used even in methods having void return type without explicitly mentioning the throw keyword. Ofcourse in such places some IDEs may warn of UnusedReturnValue but that can be suppressed as well.

Lokesh
  • 557
  • 4
  • 13