@CanIgnoreReturnValue // TODO(kak): @CheckReturnValue
  @Partially.GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class")
  public static <V, X extends Throwable> ListenableFuture<V> catchingAsync(
      ListenableFuture<? extends V> input,
      Class<X> exceptionType,
      AsyncFunction<? super X, ? extends V> fallback) {
    return AbstractCatchingFuture.create(input, exceptionType, fallback);
  }
@ CanIgnoreReturnValue @ Partially . GwtIncompatible ( "AVAILABLE but requires exceptionType to be Throwable.class" ) public static < V , X extends Throwable > ListenableFuture < V > catchingAsync ( ListenableFuture < ? extends V > input , Class < X > exceptionType , AsyncFunction < ? super X , ? extends V > fallback ) { return AbstractCatchingFuture . create ( input , exceptionType , fallback ) ; }
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 AsyncFunction#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 examples:

<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.catchingAsync(
fetchCounterFuture, FetchException.class,
new AsyncFunction<FetchException, Integer>() {
public ListenableFuture<Integer> apply(FetchException e) {
return immediateFuture(0);
}
});}</pre>

<p>The fallback can also choose to propagate the original exception when desired:

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

// Falling back to a zero counter only in case the exception was a
// TimeoutException.
ListenableFuture<Integer> faultTolerantFuture = Futures.catchingAsync(
fetchCounterFuture, FetchException.class,
new AsyncFunction<FetchException, Integer>() {
public ListenableFuture<Integer> apply(FetchException e)
throws FetchException {
if (omitDataOnFetchFailure) {
return immediateFuture(0);
}
throw e;
}
});}</pre>

<p>This overload, which does not accept an executor, uses {@code directExecutor}, a dangerous
choice in some cases. See the discussion in the {@link ListenableFuture#addListener
ListenableFuture.addListener} documentation. The documentation's warnings about "lightweight
listeners" refer here to the work done during {@code AsyncFunction.apply}, not to any work done
to complete the returned {@code Future}.

@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 AsyncFunction} 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.
@since 19.0 (similar functionality in 14.0 as {@code withFallback})