我有这个代码:
Object s = ofNullable(resp).map(ResponseEntity::getBody).orElse(ex.getMessage());
ResponseEntity::getBody returns Object and ex.getMessage returns String
我得到一个编译器错误:
The method orElse(capture#10-of ?) in the type Optional<capture#10-of ?> is not applicable for the arguments (String)
但我可以在没有可选的情况下写这篇文章,它运行良好:
Object s = resp != null ? resp.getBody() : ex.getMessage();
问题源于Java如何进行类型推理。
方法引用(和lambdas(是多表达式。这意味着同一个表达式可以有不同的类型,这取决于它在哪里使用。
所以,你的多表达:
ofNullable(resp).map(obj1::get1)
具有某种类型。
如果你要在任务上下文中使用它:
Optional<Object> opt1 = ofNullable(resp).map(obj1::get1);
Optional<?> opt2 = ofNullable(resp).map(obj1::get1);
那么这两者都可以,因为类型推断约束允许option的类型参数与变量的类型参数匹配。
但是,如果您将表达式用作另一个方法调用的接收器:
ofNullable(resp).map(obj1::get1).orElse(...)
然后Java首先推断ofNullable(...).map(...)
的类型(它不再是多表达式(,然后进行到orElse
。
很明显,obj1.get1(resp)
并没有像您所声称的那样返回Object
,而是返回一些通配符类型。这是可选项的推断类型:Optional<some wildcard>
。那么orElse
的参数也必须是some wildcard
类型;其唯一可能的值是CCD_ 8。
有很多方法可以解决这个问题:
您可以显式地将
ofNullable(...).map(...)
的结果分配给类型为Optional<Object>
的变量,然后在该变量上调用orElse
;你可以投射到
Optional<Object>
:((Optional<Object>) ofNullable(...).map(...)).orElse(...)
您可以显式映射到Object:
ofNullable(...).map(...).map(Object.class::cast)
您可以使用lambda,并将结果强制转换为
Object
:ofNullable(...).map(r -> (Object) ...).orElse(...)
或者你可以保持简单,不要尝试使用Optional
:
Object s = (resp != null) ? obj1.get(resp) : ex.getMessage();