guava/src/com/google/common/util/concurrent/Futures.java
@Beta
  @Partially.GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class")
  public static <V, X extends Throwable> ListenableFuture<V> catching(
      ListenableFuture<? extends V> input,
      Class<X> exceptionType,
      Function<? super X, ? extends V> fallback,
      Executor executor) {
    return AbstractCatchingFuture.create(input, exceptionType, fallback, executor);
  }
@Beta
  @Partially.GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class")
  public static <V, X extends Throwable> ListenableFuture<V> catching(
      ListenableFuture<? extends V> input,
      Class<X> exceptionType,
      Function<? super X, ? extends V> fallback,
      Executor executor) {
    return AbstractCatchingFuture.create(input, exceptionType, fallback, executor);
  }
Returns a {@code Future} whose result is taken from the given primary {@code input} or, if the
primary input fails with the given {@code exceptionType}, from the result provided by the
{@code fallback}. {@link Function#apply} is not invoked until the primary input has failed, so
if the primary input succeeds, it is never invoked. If, during the invocation of {@code
fallback}, an exception is thrown, this exception is used as the result of the output {@code
Future}.

<p>Usage example:

<pre>{@code
ListenableFuture<Integer> fetchCounterFuture = ...;

// Falling back to a zero counter in case an exception happens when
// processing the RPC to fetch counters.
ListenableFuture<Integer> faultTolerantFuture = Futures.catching(
fetchCounterFuture, FetchException.class, x -> 0, directExecutor());
}</pre>

<p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener}
documentation. All its warnings about heavyweight listeners are also applicable to heavyweight
functions passed to this method.

@param input the primary input {@code Future}
@param exceptionType the exception type that triggers use of {@code fallback}. The exception
type is matched against the input's exception. "The input's exception" means the cause of
the {@link ExecutionException} thrown by {@code input.get()} or, if {@code get()} throws a
different kind of exception, that exception itself. To avoid hiding bugs and other
unrecoverable errors, callers should prefer more specific types, avoiding {@code
Throwable.class} in particular.
@param fallback the {@link Function} to be called if {@code input} fails with the expected
exception type. The function's argument is the input's exception. "The input's exception"
means the cause of the {@link ExecutionException} thrown by {@code input.get()} or, if
{@code get()} throws a different kind of exception, that exception itself.
@param executor the executor that runs {@code fallback} if {@code input} fails
@since 19.0