简体   繁体   中英

what's the differences between Supplier<X> and Supplier<? extends X>

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>Supplier<? extends X> .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM