As discussed in Bounding generics with 'super' keyword the Java type system is broken/incomplete when it comes to lower bounds on method generics. Since Optional is now part of the JDK, I'm starting to use it more and the problems that Guava encountered with their Optional are starting to become a pain for me. I came up with a decent work around, but I'm not sure its safe. First, let me setup the example:
public class A {}
public class B extends A {}
I would like to be able to declare a method like:
public class Cache {
private final Map<String, B> cache;
public <T super B> Optional<T> find(String s) {
return Optional<T>.ofNullable(cache.get(s));
}
}
So that both of the following work:
A a = cache.find("A").orElse(new A())
B b = cache.find("B").orElse(new B())
As a workaround, I have a static utility method as follows:
public static <S, T extends S> Optional<S> convertOptional(Optional<T> optional) {
return (Optional<S>)optional;
}
So my final question, is this as type-safe as the 'ideal' code above?
A a = OptionalUtil.<A,B>convertOptional(cache.find("A")).orElse(new A());
You're effectively trying to view the Optional<B>
returned as an Optional<A>
without changing the return type (since you can't use the super
). I would just map
the identity function.
A a = cache.find("A").map(Function.<A> identity()).orElse(new A());
// or shorter
A a = cache.find("A").<A> map(x -> x).orElse(new A());
I don't see anything wrong with your approach though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With