javagenericsoption-typeparameterized-constructor

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?


Solution

    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.