In "Optional" source code, I found this function:
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
My question is if I change the function to this, it looks like working same
public <X extends Throwable> T orElseThrow(Supplier<X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
Anyone know the reason?
Consider this method:
void example() throws IOException {
throw new FileNotFoundException();
}
This declares that it throws the general IOException
, but concretely throws a more specific exception, FileNotFoundException
.
Same with orElseThrow
: by accepting an upper-bounded supplier, it can throw a more specific exception type.
The difference is irrelevant in most cases, because you can always catch/throws
a more general exception type. A case where I can think it may make a difference is when you are accepting the Supplier
as a parameter:
<X extends IOException> void example(Supplier<? extends X> exceptionSupplier)
throws IOException { // Note IOException, not X.
Optional.empty().orElseThrow(exceptionSupplier);
}
You can invoke this with either of the following suppliers as the argument:
Supplier<IOException> s1 = IOException::new;
Supplier<FileNotFoundIOException> s2 = FileNotFoundIOException::new;
but you couldn't do the latter without the upper bound on Supplier<? extends X>
.