I would write a method like this:
@SuppressWarnings("unchecked") // Safe. See below. static <T> Optional<T> copyOf(Optional<? extends T> opt) { return (Optional<T>) opt; }
(If you don't like the name copyOf , see my comment on Guava ImmutableList below)
This is very effective in terms of speed of execution: at startup, the execution time of the casting ends:
static <T> java.util.Optional<T> copyOf(java.util.Optional<? extends T>); Code: 0: aload_0
therefore, the only cost is the cost of invoking the method; This is easy to do using JIT.
Then you can call:
Optional<A> a = copyOf(func2());
This is safe because Optional has the following property: it is guaranteed not to have any state changes caused by setter methods using parameters that depend on a variable of type T Phew Pretty sip. I will make it more specific.
Because Optional
- it does not have setter methods (of any type, but, as a rule, there are no parameters that accept parameters of type
T , SomeGenericType<T> , etc.) - is
final (so you cannot subclass it to add a setter to break the previous point)
there is nothing that can be done for the value stored in Optional<T> (or its absence), which will make it not an instance of T (or its absence).
And since each instance of T also an instance of its superclasses, there is nothing unsafe about it:
SuperclassOfT s = optionalOfT.get();
As such, this method is type safe (it will fail if you call it optional optional, but it is not a type error).
You will find similar code in Guava ImmutableList.copyOf (the inspiration for calling it “ copyOf ” above, although this is not really a copy). There are setter methods (for example, add ), but these methods immediately throw UnsupportedOperationException s and thus do not affect the state of the list.
Please note that while immutable types have the necessary properties described above to make such a safe cast, the type does not have to be immutable for safe execution.
For example, you might have an ErasableOptional<T> type that has an erase() method on it that, when called, converts the "real" value to a "missing" value (that is, get() no longer runs), It would be safe use such an instance for ErasableOptional<SupertypeOfT> , because the value is either T or absent; you cannot make it non-instance SupertypeOfT or be absent.