Although I'm not sure why using it as Future<? extends Optional<?>>
should be a problem, there may be a solution, depending on how many contortions and "tricks" you are willing to accept.
It is not possible to compile it in the desired form, even when using the additonal type parameter E
, simply because it is not type safe. At least, it is not possible (for the compiler) to make sure that it is type safe. The reason why it could not be type safe can be summarized as follows: Someone receiving the Future<Optional<?>>
could modify the Future
, and assign it any Optional
- even one that has a different type than the one that it was originally created with. At a different location, someone could know the Future
with its original type, and receive a ClassCastException
when trying to use it. (I explained this with a simpler example in https://stackoverflow.com/a/22193221/3182664 )
But...
... all this is not relevant here. The Future
interface does not allow to "set" any new value. Thus, it is perfectly feasible to convert it into a Future
with a supertype of its original type.
Note: This is similar to the fact that you can write
List<Integer> integers = new ArrayList<Integer>();
List<Number> numbers = Collections.unmodifiableList(integers);
This is valid (meaning "type safe") because you can not pollute the Integer
-list with invalid Number
instances (like Double
s), because it's not possible to modify the list anyhow!
So one type-safe, warning-free and valid solution could be to introduce a method that "wraps" a Future<? extends T>
and returns it as a Future<T>
. Again: This is not really pretty, and may not be worth the effort, but at least one option:
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class GenericOptionalFutureMethod
{
void call()
{
Value<?> value = null;
Future<Optional<?>> future =
FutureWrapper.<Optional<?>>wrap(submit(value));
}
<T> Future<Optional<T>> submit(Value<T> value) {
return null;
}
}
class FutureWrapper
{
static <T> Future<T> wrap(final Future<? extends T> future)
{
return new Future<T>()
{
@Override
public boolean cancel(boolean mayInterruptIfRunning)
{
return future.cancel(mayInterruptIfRunning);
}
@Override
public boolean isCancelled()
{
return future.isCancelled();
}
@Override
public boolean isDone()
{
return future.isDone();
}
@Override
public T get() throws InterruptedException, ExecutionException
{
return future.get();
}
@Override
public T get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException,
TimeoutException
{
return future.get();
}
};
}
}