首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
javaWeber
V2EX  ›  Java

请教下 java8 的 Optional。。

  •  
  •   javaWeber · 8 天前 · 2304 次点击

    最近写了一堆空指针,打算改用下 java8 的 Optional 。。

    请问下以下代码,怎么用 Optional 表示。

    1. 判断 A 是否为空,然后修改 B 或者执行其他逻辑。

    想过用 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 条附言  ·  7 天前
    我这里的例子不太准确,判断的是字符串,应该改成对象的。

    我想避免对象判空,也就是用 Optional 减少 if(对象!=空)这类操作。。
    30 条回复    2020-04-01 21:43:55 +08:00
    javaWeber
        1
    javaWeber   8 天前
    3.还有就是 字符串类型的 Optional.orElse(),这里面 orElse 的默认值用什么好?

    我看网上很多用.orElse("default"),为空时就给了个默认值"default"或者"unknown"。。感觉很奇怪。
    alphatoad
        2
    alphatoad   8 天前
    用 FP 的思路就很好理解了,相当于 Haskell 的 Maybe
    data Maybe a = Nothing | Just a
    weakish
        3
    weakish   8 天前
    A 是否为空决定是否对 B 进行操作,这里对 B 的操作并没有用到 A 的值,不会碰到空指针,也就没必要用 Optional 。
    weakish
        4
    weakish   8 天前
    "default" 或者 "unknown" 这是教程里为了演示用的吧。实际场景中,就是应该用什么默认值就用什么默认值呀,原来用 `a == null ? a : "xxx"`,现在改成 `a.orElse("xxx")`,只是写法变一下,并不影响默认值的选取。
    bkmi
        5
    bkmi   8 天前 via Android
    要不用 kotlin 吧
    但是你这两个例子,看不出哪 NPE,就你现在的写法最简单了…
    lxychn
        6
    lxychn   7 天前
    不用 optional 的话判断为空的 if 忘了写就可能会出错,用了 optional 的一定要用 ifPresent()去判断,不然 compiler 就会报错,避免忘了检查是否为空的情况

    optional 好像和 lamda 结合用的更多
    xixinimei
        7
    xixinimei   7 天前
    当你意识到一个变量该用 optional 的时候,可以不用 optional 。

    Java 的 Optional 表达能力有限,主要是对自由变量的重新赋值很麻烦,需要用到容器类来包装。
    optional
        8
    optional   7 天前 via iPhone   ❤️ 3
    Optional 的精髓在 map ifpresent stream
    noreplay
        9
    noreplay   7 天前 via Android   ❤️ 2
    @optional 结合 id 来看,特别让人信服🤓🤓
    chendy
        10
    chendy   7 天前
    Optional 的有点是可以挂回调,配合其他(比如 stream ) api 可以一路点点点点写完一套逻辑,但是如果不习惯挂回调的话就很别扭
    简单场景单独判断 null 足以
    yty2012g
        11
    yty2012g   7 天前
    第一,如你图上的示例,确实使用 Optional 和判断是否等于 null 没有区别,因为你的条件分支里面没有使用 str 这个变量。在此情况下,我认为没有区别。
    第二,假如你的条件分支有使用 str,那就需要对 str 为 null 的情况赋予其他值,此时可以使用 Optional.orElse("default")或者 Optional.orElseGet(()->"default")这样的方式来代替使用 str 。
    第三,还有一种情况是 str 等于 null 我要抛异常,很常见,例如 DB 里面查不到数据我要抛异常,此时可以使用 Optional.orElseThrow(() -> new StrNotFoundException("str 没找到!"))类似的.
    综上,不是什么情况下 Optional 都能达到你想要的效果,不过最差的基本面也是和判断是否为 null 类似,所以可以尝试去使用
    guyeu
        12
    guyeu   7 天前
    @javaWeber #1 如果不知道用什么好,就用 orThrow,抛出异常。
    CommandZi
        13
    CommandZi   7 天前
    你这两个例子,不管 str 是不是 null,都不会空指针吧。
    Aresxue
        14
    Aresxue   7 天前
    optional.ifPresent(修改 B), 但就像上面说的你这个简单调用还不涉及 npe 没必要使用
    cyspy
        15
    cyspy   7 天前
    flatmap
    mezi04
        16
    mezi04   7 天前
    个人理解:把 optional 想想成盒子,of 或者 ofNullable 传入的参数就是盒子里边的东西。optional 的目的是从这个盒子里拿出一个非空数据,你可以通过一系列的方法转换盒子里的数据( fliter/flatMap ),或者告诉盒子,如果为空怎么做( orElse/ifPresent 等)。如果你的模型不符合这个,就没有用 optional 的必要
    hantsy
        17
    hantsy   7 天前
    用 orElseThrow 抛出异常就好了,我也比较常用。
    Optional<Post> post = posts.findById(id)

    post.map(....).orElseThrow(()->new PostNotFoundException(id))
    hantsy
        19
    hantsy   7 天前   ❤️ 1
    Optional 本身就是解决这中 If Null 判断,如果又回到 If 来判断,还不如不用。
    javaWeber
        21
    javaWeber   7 天前
    @CommandZi 你这两个例子,不管 str 是不是 null,都不会空指针吧。
    ==============================================
    我这里的例子写得不太准确,判断的是字符串,应该改成判断对象是否为空的。
    ```
    if(对象!=空){

    }
    ```
    MakHoCheung
        22
    MakHoCheung   7 天前
    Optional 针对的是 str 。
    这代码就算放到 kotlin 也要判 null,因为你的 str 是 String?类型
    XiLemon
        23
    XiLemon   7 天前
    可以参考一下: http://www.yinwang.org/blog-cn/2015/11/21/programming-philosophy 关于 NULL 的处理建议
    ica10888
        24
    ica10888   7 天前
    其实这个是函数式编程的东西,相当于一个包装。不过一般情况下用来处理链式操作,如 getA().getB().getC() 的空指针异常,其实 kotlin 的语法糖要好看一些...
    tachikomachann
        25
    tachikomachann   7 天前
    我的理解是用 Optional 没办法减少判空操作,而是强制你必须判空。所以一旦用了 Optional,就不会无意识地写出 NPE 问题的代码。。
    lyyhello
        26
    lyyhello   7 天前
    你看下 jdk8 用到 Optional 的地方的源码就知道了。如果有明确的返回,不用 Optional,如果因为各种原因(),结果不能保证一定为空,就用 Optional 返回。而且使用者不是简单的判断是否为空,而是和 Stream 紧密联系着用呢
    Jrue0011
        27
    Jrue0011   6 天前
    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
    CommandZi
        28
    CommandZi   6 天前
    @javaWeber Optional 设计是用来减少空指针异常,不是减少 if(对象!=空)这类操作的。你 if 后续代码都没调用对象,说明这只是你程序的固定逻辑而已,不管对象用不用 optional,都是要判断的。
    CommandZi
        29
    CommandZi   6 天前
    @CommandZi 当然这是我使用 Swift 当中的 Optional 的经验,Java 的没有了解。
    MotherShip
        30
    MotherShip   3 小时 15 分钟前
    手头上用的比较优雅的玩法大概是,Repository 层返回一个 Optional 对象,为空则直接一路把异常抛到 Controller 层然后统一处理:

    ```java
    String a = Optional.ofNullable("a").orElseThrow(()->{throw new RuntimeException();});
    ```
    至于你这两个例子。。确实用不用没啥区别
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1863 人在线   最高记录 5168   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 16:59 · PVG 00:59 · LAX 09:59 · JFK 12:59
    ♥ Do have faith in what you're doing.