【发布时间】:2018-07-04 01:58:10
【问题描述】:
TL;DR
使用可能返回 null 的函数,transform 使用 Guava Optional 的最佳(即最紧凑/可读)方式是什么? (所以在这种情况下,我们应该得到一个Optional.absent(),而不是一个 NPE。)
额外问题:如果转换器函数返回null,则在 Guava 方式中是否有优势,即抛出 NPE? (而不是将其转换为 Optional.absent(),就像在 Java 8 的情况下 Optionals 一样。)或者这只是设计的一个缺点?
问题
根据documentation of Guava Optional.transform:
与 java.util.Optional 的比较:此方法类似于 Java 8 的
Optional.map,除非函数返回null。在这种情况下 方法抛出异常,而 Java 8 方法返回Optional.absent().
示例
以下函数对两个示例都是通用的:
public String methodThatMighReturnNull(boolean returnNull, Integer input) {
return returnNull ? null : String.valueOf(input);
}
对于 Java 8,这不会引发 NPE,而是返回一个空的 Optional:
Optional<Integer> input = Optional.of(42);
Optional<String> result = input.map(new Function<Integer, String>() {
public String apply(Integer input) {
return methodThatMighReturnNull(true, input);
}
});
以下与 Guava 类似的代码会引发 NPE:
Optional<Integer> input = Optional.of(42);
Optional<String> result = input.transform(new Function<Integer, String>() {
public String apply(Integer input) {
return methodThatMighReturnNull(true, input);
}
});
可能的替代方案
我已经找到/考虑了一些替代方案,但如下所述,所有替代方案都有问题:
-
将返回值包装成
Optional。问题:太繁琐,更难阅读;Optional<Integer> input = Optional.of(42); Optional<String> result = input.transform(new Function<Integer, Optional<String>>() { public Optional<String> apply(Integer input) { return fromNullable(methodThatMighReturnNull(true, input)); } }).get(); -
通过检查
ifPresent使用if/else。问题:有点扼杀Optional的意义。 (我们可以只使用引用并检查null。)Optional<Integer> input = Optional.of(42); Optional<String> result; if (input.isPresent()) { result = fromNullable(methodThatMighReturnNull(true, input.get())); } else { result = Optional.absent(); } -
只需应用该函数,并将其包装在
fromNullable中。 (如在GitHub 上找到的,似乎已经提出了相同的问题。)问题:这与原始示例略有不同。在这种情况下,methodThatMighReturnNull最终可能会收到null,而在最初的情况下这是不可能的。Optional<Integer> input = Optional.of(42); Optional<String> result; result = fromNullable(new Function<Integer, String>() { public String apply(Integer input) { return methodThatMighReturnNull(true, input); } }.apply(input.orNull()));
【问题讨论】:
-
Java 8+ 中的 Guava 代码? Lambdas 将使 #1 和 #3 更可口。
-
更实用的方法是使用
flatMap()来确保您始终映射到正确的范围。 -
这是哪个版本的 Java?