最近写了一堆空指针,打算改用下 java8 的 Optional 。。
请问下以下代码,怎么用 Optional 表示。
想过用 if (isPresent())去判空,又觉得跟之前的 if 没什么区别。。
String str="123";
String result="abc";
if(str!=null){
result+="def";
}
2.判断 A 是否为空,然后根据情况执行 if else 里面的逻辑。。
java9 有个 ifPresentOrElse(),不过项目里用的是 java8 。
String str="123";
String result="abc";
if(str!=null){
result+="def";
}else {
result+="ghi";
}
1
javaWeber OP 3.还有就是 字符串类型的 Optional.orElse(),这里面 orElse 的默认值用什么好?
我看网上很多用.orElse("default"),为空时就给了个默认值"default"或者"unknown"。。感觉很奇怪。 |
2
alphatoad 2020-03-25 00:32:33 +08:00
用 FP 的思路就很好理解了,相当于 Haskell 的 Maybe
data Maybe a = Nothing | Just a |
3
weakish 2020-03-25 00:33:10 +08:00
A 是否为空决定是否对 B 进行操作,这里对 B 的操作并没有用到 A 的值,不会碰到空指针,也就没必要用 Optional 。
|
4
weakish 2020-03-25 00:37:50 +08:00
"default" 或者 "unknown" 这是教程里为了演示用的吧。实际场景中,就是应该用什么默认值就用什么默认值呀,原来用 `a == null ? a : "xxx"`,现在改成 `a.orElse("xxx")`,只是写法变一下,并不影响默认值的选取。
|
5
bkmi 2020-03-25 00:53:26 +08:00 via Android
要不用 kotlin 吧
但是你这两个例子,看不出哪 NPE,就你现在的写法最简单了… |
6
lxychn 2020-03-25 04:32:29 +08:00
不用 optional 的话判断为空的 if 忘了写就可能会出错,用了 optional 的一定要用 ifPresent()去判断,不然 compiler 就会报错,避免忘了检查是否为空的情况
optional 好像和 lamda 结合用的更多 |
7
xixinimei 2020-03-25 05:09:01 +08:00
当你意识到一个变量该用 optional 的时候,可以不用 optional 。
Java 的 Optional 表达能力有限,主要是对自由变量的重新赋值很麻烦,需要用到容器类来包装。 |
8
optional 2020-03-25 08:01:27 +08:00 via iPhone 3
Optional 的精髓在 map ifpresent stream
|
10
chendy 2020-03-25 08:23:11 +08:00
Optional 的有点是可以挂回调,配合其他(比如 stream ) api 可以一路点点点点写完一套逻辑,但是如果不习惯挂回调的话就很别扭
简单场景单独判断 null 足以 |
11
yty2012g 2020-03-25 08:45:02 +08:00
第一,如你图上的示例,确实使用 Optional 和判断是否等于 null 没有区别,因为你的条件分支里面没有使用 str 这个变量。在此情况下,我认为没有区别。
第二,假如你的条件分支有使用 str,那就需要对 str 为 null 的情况赋予其他值,此时可以使用 Optional.orElse("default")或者 Optional.orElseGet(()->"default")这样的方式来代替使用 str 。 第三,还有一种情况是 str 等于 null 我要抛异常,很常见,例如 DB 里面查不到数据我要抛异常,此时可以使用 Optional.orElseThrow(() -> new StrNotFoundException("str 没找到!"))类似的. 综上,不是什么情况下 Optional 都能达到你想要的效果,不过最差的基本面也是和判断是否为 null 类似,所以可以尝试去使用 |
13
CommandZi 2020-03-25 10:19:42 +08:00
你这两个例子,不管 str 是不是 null,都不会空指针吧。
|
14
Aresxue 2020-03-25 10:35:29 +08:00
optional.ifPresent(修改 B), 但就像上面说的你这个简单调用还不涉及 npe 没必要使用
|
15
cyspy 2020-03-25 10:52:24 +08:00
flatmap
|
16
mezi04 2020-03-25 11:26:19 +08:00
个人理解:把 optional 想想成盒子,of 或者 ofNullable 传入的参数就是盒子里边的东西。optional 的目的是从这个盒子里拿出一个非空数据,你可以通过一系列的方法转换盒子里的数据( fliter/flatMap ),或者告诉盒子,如果为空怎么做( orElse/ifPresent 等)。如果你的模型不符合这个,就没有用 optional 的必要
|
17
hantsy 2020-03-25 13:42:43 +08:00
用 orElseThrow 抛出异常就好了,我也比较常用。
Optional<Post> post = posts.findById(id) post.map(....).orElseThrow(()->new PostNotFoundException(id)) |
18
hantsy 2020-03-25 13:46:49 +08:00
|
19
hantsy 2020-03-25 13:48:15 +08:00 1
Optional 本身就是解决这中 If Null 判断,如果又回到 If 来判断,还不如不用。
|
20
hantsy 2020-03-25 13:50:25 +08:00
|
21
javaWeber OP @CommandZi 你这两个例子,不管 str 是不是 null,都不会空指针吧。
============================================== 我这里的例子写得不太准确,判断的是字符串,应该改成判断对象是否为空的。 ``` if(对象!=空){ } ``` |
22
MakHoCheung 2020-03-25 14:07:25 +08:00
Optional 针对的是 str 。
这代码就算放到 kotlin 也要判 null,因为你的 str 是 String?类型 |
23
XiLemon 2020-03-25 16:50:55 +08:00
可以参考一下: http://www.yinwang.org/blog-cn/2015/11/21/programming-philosophy 关于 NULL 的处理建议
|
24
ica10888 2020-03-25 17:39:44 +08:00
其实这个是函数式编程的东西,相当于一个包装。不过一般情况下用来处理链式操作,如 getA().getB().getC() 的空指针异常,其实 kotlin 的语法糖要好看一些...
|
25
tachikomachann 2020-03-25 17:54:23 +08:00
我的理解是用 Optional 没办法减少判空操作,而是强制你必须判空。所以一旦用了 Optional,就不会无意识地写出 NPE 问题的代码。。
|
26
lyyhello 2020-03-25 18:57:11 +08:00
你看下 jdk8 用到 Optional 的地方的源码就知道了。如果有明确的返回,不用 Optional,如果因为各种原因(),结果不能保证一定为空,就用 Optional 返回。而且使用者不是简单的判断是否为空,而是和 Stream 紧密联系着用呢
|
27
Jrue0011 2020-03-26 10:46:30 +08:00
Optional 要用上 map/flatMap 、filter 。一般应该是一段代码调用多个方法,每个方法入参都是上个方法返回值或返回值部分,Optional 的 map/flatMap 可以避免对每个返回值判断 null,如果对返回值的判断不仅仅是否 null 的话,可以用 filter 判断。
比如这样。。。 Optional.of(userId).map(userDao::getPhone).filter(phoneService::isChinaMobile).ifPresent(smsService::sendMsg); Optional.of(userId).map(userDao::getPhone).map(phoneBook::getContactListByPhone).orElseGet(Collections::emptyList); 或者如果有需要抛业务异常,也可以用 orElseThrow |
28
CommandZi 2020-03-26 11:15:28 +08:00
@javaWeber Optional 设计是用来减少空指针异常,不是减少 if(对象!=空)这类操作的。你 if 后续代码都没调用对象,说明这只是你程序的固定逻辑而已,不管对象用不用 optional,都是要判断的。
|
30
MotherShip 2020-04-01 21:43:55 +08:00
手头上用的比较优雅的玩法大概是,Repository 层返回一个 Optional 对象,为空则直接一路把异常抛到 Controller 层然后统一处理:
```java String a = Optional.ofNullable("a").orElseThrow(()->{throw new RuntimeException();}); ``` 至于你这两个例子。。确实用不用没啥区别 |
31
facelezz 2020-08-13 10:06:24 +08:00
楼上回答了那么多,其实 guava 文档里就有解释。
Besides the increase in readability that comes from giving null a name (增加了可读性,isPresent()比 if xxx!=null 可读性好) the biggest advantage of Optional is its idiot-proof-ness.It forces you to actively think about the absent case if you want your program to compile at all, since you have to actively unwrap the Optional and address that case (使用了 option 后,强迫你思考不存在的情况,避免忘记) This is especially relevant when you're returning values that may or may not be "present." You (and others) are far more likely to forget that other.method(a, b) could return a null value than you're likely to forget that a could be null when you're implementing other.method. Returning Optional makes it impossible for callers to forget that case, since they have to unwrap the object themselves for their code to compile. (对设计的优化,如果你的方法返回值可能存在也可能不存在,就尽量返回 optional,这样别人用你的方法就知道需要判断) 至于 orElse 这种类型操作,我自己理解的是 4 楼那样,此外,optional 并不是用来简化流程,只是一种设计,让人记住去处理 null |