0

Suppose I have an Optional<Exception> and want to cast it to an Optional<Throwable>. Are there any prettier ways of doing this rather than:

Optional<Exception> optionalException = Optional.of(new Exception());
Optional<Throwable> optionalThrowable = (Optional<Throwable>) (Optional<? extends Throwable>) optionalException;

This solution generates a lint warning in IntelliJ.

Unchecked cast: 'java.util.Optional<capture<? extends java.lang.Throwable>>' to 'java.util.Optional<java.lang.Throwable>'
Michael
  • 41,989
  • 11
  • 82
  • 128
whitebrow
  • 2,015
  • 21
  • 24
  • 1
    "SupressWarnings("unchecked") might be better than `.map()` here. https://stackoverflow.com/questions/1129795/what-is-suppresswarnings-unchecked-in-java – markspace Apr 06 '20 at 15:37

2 Answers2

4

Found it:

Optional<Exception> optionalException = Optional.of(new Exception());
Optional<Throwable> optionalThrowable = optionalException.map(Function.identity());
whitebrow
  • 2,015
  • 21
  • 24
  • If you want to use `.orElseGet(() -> new Throwable())` on the optional without storing it in the intermediate `Optional optionalThrowable` variable, you can use `.map(Function.identity())` or `.map(Function.identity())` as a type hint. You could also use `.map((Throwable t) -> t)`. In all three cases you prevented the use of an unsafe class cast. If you do make the `Optional optionalThrowable` variable, you can just do `.map(t -> t)` – Rik Schaaf Jul 26 '23 at 23:31
2

Your solution is OK, but has the downside of creating a new Optional instance.

An alternative is to write a utility method, in which you can suppress the warning just once:

@SuppressWarnings("unchecked")  // Safe covariant cast.
static <T> Optional<T> upcast(Optional<? extends T> opt) {
  return (Optional<T>) opt;
}

and then just use this in all the places without warnings.

But better (if you have the control to do so) is to fix the place where you need an Optional<Throwable> to accept an Optional<? extends Throwable>.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • 2
    Did you forget you wrote this? :) https://stackoverflow.com/a/44853739/1898563 – Michael Apr 06 '20 at 15:44
  • @Michael yep. I write lots. – Andy Turner Apr 06 '20 at 15:47
  • 1
    In principle, the implementation of `Optional.map` could skip the creation of a new `Optional` instance when the resulting reference is identical to the old. However, the creation of an `Optional` might not be expensive enough to justify spending time on such an optimization. – Holger Apr 07 '20 at 12:04