2022-03-31

Bad return type in lambda expression when using Java's Optional.or() with subclasses

I am trying to use Optional.or to get an object of subclass A or, if empty, an object of subclass B:

interface Node {}
class InnerNode implements Node {}
class LeafNode implements Node {}
Optional<InnerNode> createInnerNode() {}
Optional<LeafNode> createLeafNode() {}

Optional<Node> node = createInnerNode().or(() -> createLeafNode());

When doing this, I get the following compiler error:

Bad return type in lambda expression: Optional<LeafNode> cannot be converted to Optional<? extends InnerNode>

If I instead use wildcards to explicitly tell the compiler that the Optionals contain an object extending from Node:

Optional<? extends Node> optionalInner = createInnerNode();
Optional<? extends Node> optionalLeaf = createLeafNode();
Optional<Node> node = optionalInner.or(() -> optionalLeaf);

I get the following compiler error:

Bad return type in lambda expression: Optional<capture of ? extends Node> cannot be converted to Optional<? extends capture of ? extends Node>

The only way I found to make this work, is using an Optional.empty in front:

Optional<Node> node = Optional.<Node>empty() // requires generic argument
    .or(() -> createInnerNode())
    .or(() -> createLeafNode());

But for me, this is confusing to read. Is it somehow possible to instruct the compiler to allow the statement optionalInner.or(() -> optionalLeaf)? Or are there other alternatives to make this work?



No comments:

Post a Comment