Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Optional.orElseThrow signature explanation

I looked at the Optional class method orElseThrow out of curiosity and I got confused of its signature. I didn't understand why it has to be declared as it is. So, I did an experiment with a copy of the original orElseThrow method and my simplified variant:

public class Main<T> {

    //This is original signature of Optional.orElseThrow method 
    public  <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X{

            throw exceptionSupplier.get();
    }

    //This is my attempt to simplify it but it doesn't work without try-catch block
    public T orElseThrow2(Supplier<Throwable> exceptionSupplier) throws Throwable{

        throw exceptionSupplier.get();
    }

    public static void main(String[] args){
        Main<Object> m = new Main<Object>();

            m.orElseThrow(() -> new RuntimeException("ha")); //no warnings/errors shown

            m.orElseThrow2(() -> new RuntimeException("sad")); //"Unhandled exception: java.lang.Throwable"
}
  1. Why my method is not accepted without a try-catch block?

  2. Why extending Throwable as in the original method doesn't require a try-catch block even though original method throws a Throwable object?

like image 272
CuriousGuy Avatar asked Jan 02 '23 05:01

CuriousGuy


2 Answers

  1. Because all the compiler knows about your method is that is throws a Throwable. Since the Throwable could thus be a checked exception, you're forced to declare it in the throws clause or to catch it.

  2. Because the compiler knows that the method throws X, where the generic type X is inferred as RuntimeException: () -> new RuntimeException("ha") is a Supplier<RuntimeException>. And runtime exceptions, by definition, are unchecked exceptions that don't need to be declared in the throws clause.

like image 88
JB Nizet Avatar answered Jan 11 '23 09:01

JB Nizet


To clarify one step further:

Having a generic exception (throws X) is giving flexibility.

If you return a checked exception while using the first signature:

m.orElseThrow(() -> new Exception("ha"));

The compiler gives the error (Unhandled Exception) as well because it knows that some checked exceptions might be thrown. However, supplying RuntimeException gives the sign to the compiler that it is an unchecked exception.

On the other hand, in your custom method, you are making sure that it will always throw Throwable, which requires handling.

like image 41
turkogluc Avatar answered Jan 11 '23 09:01

turkogluc