Java 中的 Optional 应该什么时候用呢,总感觉这样不如直接 if 判断

2023-08-26 17:23:22 +08:00
 baolinliu442k

4940 次点击
所在节点    Java
39 条回复
yechentide
2023-08-26 19:51:24 +08:00
@Edward4074 Swift !
baolinliu442k
2023-08-26 19:52:51 +08:00
@yechentide dart 里好像也有这个
Building
2023-08-26 20:01:16 +08:00
惊到我了,以前看到 Java 新增 Optional Value 的时候我还想越来越现代化了,没想到这个老太太的裹脚布果然没让我失望
fpure
2023-08-26 20:29:01 +08:00
说实话,没多大用,不如 @NotNull 和 @Nullable
cyningxu
2023-08-26 22:31:12 +08:00
kotlin:就这?
caiqichang
2023-08-26 23:48:59 +08:00
kotlin 更优雅
val jobName = people?.job?.jobName ?: null
humpy
2023-08-27 00:36:17 +08:00
基本不用,这就是个 nullability 的残废实现,慢慢等 https://mail.openjdk.org/pipermail/valhalla-spec-experts/2023-May/002276.html
netabare
2023-08-27 01:05:45 +08:00
一般是用 orElse 、flatMap 来串接不同的处理过程的吧。
if isPresent 这个写法太命令式了。直接 get 的话说实话不如不要用 Optional 。
当然 Optional 确实很难用就是了。
cheng6563
2023-08-27 01:10:18 +08:00
烂设计,没有必要用。
lisongeee
2023-08-27 01:37:13 +08:00
kotlin: val jobName = people?.job?.jobName ?: null
js/ts: const jobName = people?.job?.jobName?.[0] ?? null
c#: var jobName = people?.job?.jobName?[0] ?? null
Swift: let value = obj?.nestedObj?.property
dart: var jobName = people?.job?.jobName ?: null

但是肯定有人觉得 Optional 比上面更好用,毕竟祖宗之法不可变
ikas
2023-08-27 09:56:56 +08:00
复制一点实际业务代码

var fileName = file.getName();
var fileInfo = new FileInfo();
SessionContext.userName().ifPresent(fileInfo::setUserName);
MediaTypeFactory.getMediaType(fileName).map(MediaType::toString).ifPresent(fileInfo::setContentType);
Bingchunmoli
2023-08-27 11:28:59 +08:00
@lisongeee 有时候??多了有点增加阅读难度,当然也是因为用的不多不够熟悉 kt 。.let 复杂点 ide 提示的自己都看不懂
tamer
2023-08-27 11:45:51 +08:00
不是拿来单独取代 if 判断的
是拿来写 lambda 的
PTLin
2023-08-27 14:32:19 +08:00
我还记得以前有人笑过 Optional ,大概是说 Java 的 Maybe 居然有三种状态:Just ,Noting 和 NULL 。
FrankHB
2023-08-27 15:19:43 +08:00
@lisongeee null 就是个阉割版的 Optional ,而且明显更祖宗。
Optional 本身本来也不是太大的问题(起码回避起来比起无处不在的 null 来说容易多了),问题是 null 这祖宗干不掉,又另外加上 Optional ,本该是同一种目的凭空多出来不同的不兼容的表达方式乃至于扭曲目的本身(不顾历史,强行为现状洗地而寻找不同的用例场合),混起来效果就很感人了。
FrankHB
2023-08-27 15:34:54 +08:00
@PTLin 多几种其实不是直接问题。上古的 cons pair 限制个别元素就能造出 list monad ,用比较现代一点的说法,决定限制的 unit predicate 是 null?;中古一点的 string 同样也是个 monad ,unit pred 是 string-null? 。其实吧,传统数学上 list 和 string 可以就是一回事。那为什么不嫌弃 string 和 list 共存冗余呢?因为 string 好歹有复杂度 hint 表明适合不同场景(激进一点的还有 encoding 甚至 SSO 之类的假设,但把本属于 text 的东西混同 string 有过度设计的问题,这又是另一回事了)。这个意义上 string 是具有更多实现假设的 list 又确实不都能替代 string ,这种不同层次上的冗余适应新的需求,其实不难接受。
问题是引入的目的和过程。新增的抽象如果没有提供更详细的假设提升到接口的含义,而仅仅是为了给不完善的旧有抽象擦屁股,但被擦屁股的东西又因为兼容性之类的原因没法被彻底替代而只能共存,这样缝合的下场自然不会让用户舒服了。
为什么说 null 是多余的呢?因为 nullable type 历史上本来就是实现偷懒( null pointer )的结果上反向臆造的抽象。要从需求侧讲,没什么和 Maybe 区分的必要,反倒是传统实现习惯(比如死板的错误处理)导致使用者体验很尴尬。相比之下,C++一样也有 optional<T&>不能随便和 T*等价的历史包袱,这里思想包袱就体现得更明显,因为 nullptr 并没有 Java 一样被迫弄得到处都是的存在感,兼容性问题本该不是借口。
lisongeee
2023-08-27 15:36:31 +08:00
@FrankHB

null 我觉得还好,不好的点是没有把 null 做到编译期,实际上可 null 就是一个简单的联合类型

如果把 null 像 kotlin/ts/c#/Swift/dart 直接做到编译期,我觉得就没啥问题了

Optional 太长太难用了,还是编译期 null 校验+可选链更好用
Kaiv2
2023-08-27 16:09:12 +08:00
补充一个小点: 在 JDK8 时,使用 Optional 总感觉少了个功能, 在一堆链式调用后,
只有 ifPresent 方法, 不为空的情况下才能执行, 还是需要 if 语句来判断是否为空。
后面发现 JDK9 添加了一个 ifPresentOrElse 方法来解决这个问题。
Kaiv2
2023-08-27 16:18:00 +08:00
@Kaiv2 补充代码

People p = null; // TODO:
Optional<People> people = Optional.ofNullable(p);
Map<String, String> result = new HashMap<>();
people.map(People::getUsername)
.ifPresentOrElse(e -> {
result.put("status", "1");
result.put("name", e);
}, () -> {
result.put("status", "?");
});

System.out.println(result);

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/968493

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX