Reputation: 573
Exploring the classes in guava to understand the benefits what guava brings, even though with the introduction of java 8, it does not matter that much now, but I am still wondering about how listenableFuture is introduced.
in AbstractListeningExecutorService, there is code snippet like this:
@Override
public ListenableFuture<?> submit(Runnable task) {
return (ListenableFuture<?>) super.submit(task);
}
here super
indicates the super class of AbstractListeningExecutorService, namely ExecutorService, but how can we just cast a superclass (Future) to a subclass (ListenableFuture) like this ?
Upvotes: 1
Views: 859
Reputation: 279950
You'll notice the direct superclass of AbstractListeningExecutorService
is AbstractExecutorService
which
Provides default implementations of
ExecutorService
execution methods. This class implements the submit,invokeAny
andinvokeAll
methods using aRunnableFuture
returned bynewTaskFor
, which defaults to theFutureTask
class provided in this package.
That default is overriden in AbstractListeningExecutorService
Abstract
ListeningExecutorService
implementation that createsListenableFuture
instances for eachRunnable
andCallable
submitted to it
You can also see that in the source code you linked to
/** @since 19.0 (present with return type {@code ListenableFutureTask} since 14.0) */
@Override
protected final <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return TrustedListenableFutureTask.create(runnable, value);
}
That create
returns a TrustedListenableFutureTask
value, which is a subtype of ListenableFuture
.
Those methods in AbstractListeningExecutorService
are redeclared so that their return type can be made more specific, ie. ListenableFuture
.
Since super.submit(..)
has a return type of Future
, the return value must be cast to the appropriate subtype, ie. ListenableFuture
in this case. And since all calls return the instance created by newTaskFor
, it is known that they will be instances of type ListenableFuture
. The cast is therefore safe.
Upvotes: 3