Java8通用拼图

时间:2017-11-20 12:53:58

标签: java generics java-8 optional

我正在使用Java 1.8.0_151,有些代码无法编译,我不明白:

Optional optional = Optional.of("dummy"); 
Optional<Boolean> result1 = optional.map(obj -> true);     // works fine
boolean result2 = result1.orElse(false);                   // works fine
boolean result3 = optional.map(obj -> true).orElse(false); // compilation error: Incompatible types: required boolean, found object
Object result4 = optional.map(obj -> true).orElse(false); // works fine

为什么它在result1上正常工作但在result3上出现编译错误? 其他信息:

  • 在第一行,当我将Optional更改为Optional<String>时,result3也可以编译
  • 当我将result3分成两行时:result1result2result3能够编译

3 个答案:

答案 0 :(得分:9)

一旦你失去了类型安全性 - 它也会因链式通话而丢失。那是Optional<Object> != Optional。所以当你这样做时

 Optional optional = Optional.of("dummy");
 optional.map()

map只能接受原始Function而不接受任何其他内容,这显然会返回Object

正确的方法是添加类型信息:

Optional<String> optional = Optional.of("dummy");

或者你可以不安全地投射:

boolean result3 = (boolean) optional.map(obj -> true).orElse(false)

答案 1 :(得分:4)

optional是原始Optional,因此optional.map(obj -> true)返回原始Optional,而orElse(false)返回Object,而不是Boolean 1}}。编译器不知道如何取消Objectboolean

通过更改

Optional optional = Optional.of("dummy"); 

Optional<Object> optional = Optional.of("dummy"); 

Optional<String> optional = Optional.of("dummy"); 

您将克服此错误,因为现在optional.map(obj -> true)将返回Optional<Boolean>orElse(false)将返回Boolean

答案 2 :(得分:0)

感谢您的回答。我只是想详细介绍一下它在resutl1上的工作原理,而不是result3

Optional<Boolean> result1 = optional.map(obj -> true);     // works fine
boolean result2 = result1.orElse(false);                   // works fine
boolean result3 = optional.map(obj -> true).orElse(false); // compilation error: Incompatible types: required boolean, found object
<{1>} result1上的optional变量是原始类型,因此optional.map(obj -> true)返回了Optional原始类型。

当我宣布Optional<Boolean> result1时,Optional原始类型自动投放Optional<Boolean>
另一方面,optional.map(obj -> true).orElse(false);失败,因为原始类型Optional对象无法调用.orElse(false)

原始类型的此行为的另一个示例是:

List li = new ArrayList<String>();
List<String> li1 = li;
List<Integer> li2 = li;
List<Map> li3 = li;

li1.add("WWW");
li2.add(444);
li3.add(new HashMap());

适用于所有场景,li对象将包含String,Integer和HashMap()。 li1, li2, li3被自动转换为非原始类型。