我有此代码:
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();
答案 0 :(得分:2)
问题源于Java如何进行类型推断。
方法引用(和lambda)是 polyexpressions 。这意味着相同的表达式可以具有不同的类型,具体取决于使用的位置。
因此,您的多表达式:
ofNullable(resp).map(obj1::get1)
具有 some 类型。
如果要在分配上下文中使用它:
Optional<Object> opt1 = ofNullable(resp).map(obj1::get1);
Optional<?> opt2 = ofNullable(resp).map(obj1::get1);
然后这两个都很好,因为类型推断约束允许可选的类型参数与变量的类型参数匹配。
但是,如果您使用表达式作为其他方法调用的接收者:
ofNullable(resp).map(obj1::get1).orElse(...)
然后Java首先推断ofNullable(...).map(...)
的类型(它不再是多表达式),然后继续进行orElse
。
很显然,obj1.get1(resp)
不会像您声明的那样返回Object
,而是返回一些通配符类型。这是可选的Optional<some wildcard>
的推断类型。那么orElse
的参数也必须为some wildcard
类型;唯一可能的值是null
。
有多种解决方法:
您可以将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();