跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • JAVA8 的 Optional 是鸡肋
未分類
29 1 月 2021

JAVA8 的 Optional 是鸡肋

JAVA8 的 Optional 是鸡肋

資深大佬 : mightofcode 6

对于处理 NPE 问题基本没有帮助

不使用 Optional,你得判空
使用 Optional,你还是得判空,只是换了一种形式
引入 Optional 降低代码可读性,代码变得丑陋

我在工作中从没见到有项目使用 Optional
除了使用 java stream 不得不用到 Optional

本质上 java 要在 null 上做优化只能通过底层语言设计上做改进(比如 Rust ),然而由于兼容性的需要,这条路已经走不通了

大佬有話說 (100)

  • 資深大佬 : Jooooooooo

    optional 强制判空, 还是有点用的

  • 資深大佬 : finab

    习惯就还挺好的,optional 用习惯了后,发现挺舒服的,现在写没有 optional 特性的语言代码时都有点不习惯了

  • 資深大佬 : Jirajine

    optional 存在的意义就是通过静态检查强制你处理为空时的情况。rust 也是这样做的。

  • 資深大佬 : fishCulturer

    感觉判空这块还是工具包香

  • 資深大佬 : yuhuan66666

    强制判空,怕你忘,对于多人协作开发,返回值加一个,挺好用的,我就喜欢用

  • 資深大佬 : sampeng

    自己水平不够就认为没用?
    感情你工作这么久从来没有或者没见过空指针?
    现在从语言层面消灭空指针不都是 optional 的方式么?

  • 資深大佬 : guyeu

    问好语法糖和 Optional 又有什么本质区别呢?我觉得 Optional 最重要的意义是提高空返回值的成本,促使程序员使用有意义的返回值代替空,只有在空有意义的情况下才返回空,这样一来,现有的绝大多数的判空就不需要写了。

  • 資深大佬 : mxT52CRuqR6o5

    你这不是 Optional 的问题,而是没有类似 Kotlin 中 Safe Calls 运算符的问题

  • 資深大佬 : sampeng

    rust 哪门子的底层语言设计上做的改进。本质上 rust 的 Option 和 Optional 的实现有任何区别不成?只是 java 有历史包袱不能让你强制所有地方都用 optional 或者具体的值。rust 没这个负担,所以可以提供?的语法糖。在没有?语法糖的时候 rust 判断 option 也是写的很恶心的

  • 資深大佬 : huifer

    private static Optional optional(){
    return null;
    }

    public static void main(String[] args) {

    System.out.println(optional().isPresent());

    }

    使用的时候是否要对 `Optional` 判空呢?

  • 資深大佬 : yuanxiaosong

    随便百度了一个例子,可以试试改成不用 Optional 需要多少代码,少用 isPresent 和 get,多使用 map 、filter 、orElse,多使用 Function 、Supplier 和 Consumer 来解决问题:

    Optional
    .ofNullable(someVariable)
    .map(this::findOtherObject)
    .filter(this::isThisOtherObjectStale)
    .map(this::convertToJson)
    .map(String::trim)
    .orElseThrow(() -> new RuntimeException(“something went horribly wrong.”));

    代码来源: https://www.jdon.com/52008

  • 資深大佬 : 11wangyaoda

    optional 最有意思的是 optional 自己有可能是 null

  • 資深大佬 : chendy

    如果是接 orThrow 直接报错的情况还好
    如果是接 orElse(null) 就显得很多余了

  • 資深大佬 : yazinnnn

    Optional.ofNullable(T value)

    用这个啊

    如果你调用的 api 的编写人员不靠谱,那就让他别返回 Optional 了

  • 資深大佬 : tamer

    @yuanxiaosong 这种例子其实很有误导性,
    实际业务代码往往并不会简单的是连续的方法引用

  • 資深大佬 : LGA1150

    @huifer @11wangyaoda 这样写 IDE 会有警告

  • 資深大佬 : arloor

    给你,你说鸡肋
    不给,你说缺失

    仔细看看自己写的代码,照样都是 trade off

    (点开看,原来不只是黑大 java,还要吹 rust,应该是最喜欢的编程语言评选又开始评选了

  • 資深大佬 : xuanbg

    很少用,一般都是直接判空。某些场景在实体类的 get 方法中处理值为空。

  • 資深大佬 : sakura1

    这个问题感觉源自 null 的存在本身

  • 資深大佬 : Takamine

    建议可以看看《 Java 核心技术卷 2 》 Optional 的部分,比结合 flatMap 使用的。

  • 資深大佬 : Takamine

    比如*。

    我觉得这个是函数式编程新进来的,不能拆开来看。

  • 資深大佬 : lemon94

    swift 也有 optional,是繁琐了点,但解决 npe 问题还算有成效。

  • 資深大佬 : hantsy

    Optional 太常用了。

    思想固化,从来没用过 Java 8 的人才会去判断是不是 NULL,把好好的代码打回 Java 8 以前。

    Optional 在 Java 8 改进了很多,和 Stream 一样,用于 Pipeline 类似操作,很方便。

    https://github.com/hantsy/spring-webmvc-jwt-sample/blob/master/src/main/java/com/example/demo/DemoApplication.java#L34-L45

    “`java

    @Bean
    public AuditorAware<User> auditor() {
    return () -> Optional.ofNullable(SecurityContextHolder.getContext())
    .map(SecurityContext::getAuthentication)
    .filter(Authentication::isAuthenticated)
    .map(Authentication::getPrincipal)
    .map(User.class::cast);
    }
    “`

    再说了以 Spring 5 为基础,核心代码还有其 Spring 生态(比如 Spring Data ) API 都是对 Java 8 API 优化,Optional 在 Spring 中已经是随处可见,难道还没升级 Spring 5 ?

  • 資深大佬 : assiadamo

    jdk 的 Optional 无法序列化且对 GC 有压力,有个好用的库叫 vavr 可以替代

  • 資深大佬 : assiadamo

    比如 netty 就不用 Optional

  • 資深大佬 : hantsy

    如果用过 Spring WebFlux ( ReactiveStreams API )就更不用说了,流式操作是必须的。

    https://github.com/hantsy/spring-reactive-jwt-sample/blob/master/src/main/java/com/example/demo/config/MongoConfig.java#L19-L28

    “`java
    @Bean
    ReactiveAuditorAware<Username> reactiveAuditorAware() {
    return () -> ReactiveSecurityContextHolder.getContext()
    .map(SecurityContext::getAuthentication)
    .filter(Authentication::isAuthenticated)
    .map(Authentication::getPrincipal)
    .map(UserDetails.class::cast)
    .map(UserDetails::getUsername)
    .map(Username::new)
    .switchIfEmpty(Mono.empty());
    }
    “`

  • 資深大佬 : EscYezi

    @tamer #15 还得看实际业务,之前确实用到过这种写法

  • 資深大佬 : Leviathann

    有时候把它当成三目用,至少比裸写三目漂亮

  • 資深大佬 : chenfcheng

    Optional.ofNullable(o1.getx().getxx().getXXX()).orElse() 这时候最有用 多层嵌套情况下 可直接设置默认值 多次判断是否为空

  • 主 資深大佬 : mightofcode

    @yuanxiaosong 这就是我说的 stream 的场景

  • 主 資深大佬 : mightofcode

    @Jooooooooo 不用 optional 抛出 NPE,用 optional,抛 NoSuchElementException

    optional 真的很鸡肋

  • 主 資深大佬 : mightofcode

    @arloor

    给我,我说鸡肋
    不给,我说可以提供一个更好的

  • 資深大佬 : zhuangzhuang1988

    ✓ 很多 fp 就是放屁

  • 資深大佬 : shyling

    黑 java 可以,但 rust 不是一样的操作?

  • 主 資深大佬 : mightofcode

    @Jirajine optional 做不到强制检查 null,你一样可以选择直接调用 get,然后抛出 NoSuchElementException

  • 主 資深大佬 : mightofcode

    @shyling rust 不一样,rust 如果声明不返回 null,那就绝对不会返回 null

  • 資深大佬 : 1011

    @hantsy
    @yuanxiaosong

    fp 这个东西怎么说呢,实际写起业务来也需要设计一番,难度不比设计类、接口这些低
    如果自己设计、抽象的功底不够好还是简单 if else 走起吧,至少写出来的东西还能看懂

  • 主 資深大佬 : mightofcode

    @LGA1150 警告不是 error,就有可能被无视

  • 主 資深大佬 : mightofcode

    @sampeng optional 消灭不了空指针,你如果能用 optional 消灭空指针,发出来大家学习下

  • 資深大佬 : yazinnnn

    不过说实话,单拿 optional 出来做 fp 确实没啥用,java 的函数式还是太弱了

  • 資深大佬 : LGA1150

    #31 如果你依赖 isPresent 和 get 方法,那就和传统的 != null 没区别
    真正有用的是 ifPresent, ifPresentOrElse, orElseGet 等的函数式方法

  • 資深大佬 : shyling

    @mightofcode std::mem::transmute 有话说

  • 資深大佬 : Jirajine

    @mightofcode 概念是一致的,给警告也算静态检查了,只要你不忽略警告,再就是它提供的那些 combinator 方法。
    kotlin 也分 nullable type,概念也是一样的,可能语法上好一点。

  • 資深大佬 : hantsy

    @yazinnnn 太弱?

    不,大约 5,6 年前,开始试用 Java8 的时候, 发现 Scala 没那么吸引人了。

    我在 Spring 项目中第一次大规模使用 Java 8 的 Function/Consumer/Supplier 是应用 Spring Integrations 4 的 Java 8 DSL,当时它是单独的模块,现在是 Spring Integration 5 核心的一部分了。

    https://spring.io/blog/2014/11/25/spring-integration-java-dsl-line-by-line-tutorial

  • 資深大佬 : hantsy

    @1011 跟业务设计有毛线关系啊。

    代码换个写法而已,不喜欢依然可以传统的方式。

  • 資深大佬 : otakustay

    最根源的问题还是`null`是一个值而不是一个类型

  • 資深大佬 : KarmaWu

    Optional 判空还是挺香的,你可以不用,但是它存在即是合理

  • 主 資深大佬 : mightofcode

    @KarmaWu 香在哪?既然合理,麻烦给一个合理分析

  • 資深大佬 : nthin0

    @chenfcheng 这样不行吧,得用.map(xx::getXXX),否则其中一个为 null 的时候还是会抛空指针

  • 資深大佬 : bigbigeggs

    主要是强制吧,和自己 xx == null 来进行判断。
    直接抛异常,他不香么

  • 資深大佬 : ilumer

    https://stackoverflow.com/questions/26327957/should-java-8-getters-return-optional-type 这个回答可能有所帮助

  • 資深大佬 : Vedar

    确实挺蛋疼的 主要还是因为不是 zero cost 的 所以还是很少用 除了一些必须要用的地方比如和 stream 交互的地方

  • 資深大佬 : Vedar

    另外 java 自带的 optional 不支持序列化 有时候也挺烦的

  • 資深大佬 : taojintianxia

    就是因为大量人员不做判空导致大家都在写防御性代码。第三方或者前端的数据我们无法保证一定非空,但是内部接口调用,我们难道无法保证参数是否为空吗。

  • 資深大佬 : LGA1150

    @Vedar #52 JIT 会优化的

  • 資深大佬 : young1lin

    怎么缩呢,这个其实有点用。Spring 源码就用到了这个,在 DefaultListableBeanFactory 这个类里面好像。可以进行流式判断,确实能省好多代码,就是没仔细学过 Java8 的容易懵逼。

  • 資深大佬 : Vedar

    @LGA1150 这怎么优化? jit 会将热点代码编译成机器码来提高速度 但是内存的申请和释放还是一样的呀,optional 包了一层对象 增加了 gc 压力 这不是一定的么

  • 資深大佬 : cigarzh

    > 给你,你说鸡肋
    > 不给,你说缺失
    我觉得还挺有道理的,不过我也反对降低代码可读性来做防御式编程

  • 資深大佬 : Aimers

    kt 大法好

  • 資深大佬 : blackboom

    个人感觉 Optional 非常普遍啊?

  • 資深大佬 : LGA1150

    @Vedar #57 new 操作也是可以被优化掉的,有个 JVM 开关是 EliminateAllocations (标量替换),默认打开的

  • 資深大佬 : namelosw

    Java 的 Optional 和 Rust 的区别不大, 可读性下降是因为缺对应的 monadic 语法糖 . 能把?.之类的语法变换成 map 和 flatMap. 这个 Java 想加也能加, 其实就是 Scala 的 for 语法.

    Rust 和 Java 不兼容的地方是 borrow checker, 但是和你说的这个问题没有关系.

    同理还有 Stream / Future 之类的和 async await 的关系.

  • 資深大佬 : hantsy

    @cigarzh 可读性很多时候是个人问题习惯而已。Scala 的语法可读性好吗?不照样有一群忠实粉丝。

    Optional/Stream/Function/Labmda,Future 等,正经项目用过一次就习惯了,你再也不想回去了。

    至于讨论“XXX 是鸡肋”这个问题本身就是鸡肋。

    如果对于一种语言新语法,讨论如果使用,与其他语言对应的语法缺少什么,有什么优点,那还算一个帖子有点正面意义。

    国内所有论坛的帖子,最多的就是在一些扯蛋的问题上撕逼。

  • 資深大佬 : fpure

    Java 的 Optional 最大的问题是即使有 Optional,你依然必须给对象判 null,因为 Java 允许空指针就已经给类型系统打了一个洞了,这时候是否使用 Optional 就意义不大了,确实算鸡肋

  • 資深大佬 : sampeng

    @mightofcode 你这就属于抬杠了,上下文意思是空指针异常啊…

  • 資深大佬 : sampeng

    @mightofcode 再说了,你认为警告没用,那是你们代码没有 review,没有静态代码检查,没有很多强制性的要求。放飞自我随便写那确实没啥区别。对于很多开发而言,在学习语言编程的一节课或者说被教育的第一件事:不要忽略警告提示。

    编码调试阶段只有两个信息,错和没错。没有中间那档。

  • 資深大佬 : Vedar

    @LGA1150 受教了 jit 还有这个功能 才知道 看了下 这个只能替换没有逃逸的对象吧,实际上 optiona 大多 l 作为函数返回值,还是优化不了的

  • 資深大佬 : AItsuki

    还行吧,optional 通过链式调用的时候是能提升阅读性的,例如 a.b().c().d()任何一环都有可能是空的情况。这种时候使用 optional 就很优雅。其他就见仁见智了。

  • 資深大佬 : Kaiv2

    @AItsuki
    Optional.ofNullable(a)
    .map(type::b)
    .map(type::c)
    .map(type::d)
    .orElse((type)null);

    Optional 个人感觉很好用,刚开始可能不习惯,思维模式转变后发现真香

  • 資深大佬 : Kaiv2

    @Kaiv2 这个例子看看不用 Optional 需要几次手动判空

  • 資深大佬 : lululau

    还有人说 Stream API 比 for (int i=0; i <n; i++) 可读性低呢

  • 資深大佬 : casillasyi

    v 站人均 jdk 开发者水平了吗?难读了,你这个结论是来自你自己的感觉还是有数据支撑?

  • 資深大佬 : WispZhan

    Optional 设计初衷是给 Lambda 和 Stream 用的,并不是单纯给你来判空与否的。

  • 資深大佬 : casillasyi

    “如果真这么好用,那么入参也应该用用起来啊。” 这前后有因果关系吗?你认真看过原作者的建议吗?

    “但是这个只是警告,是非强制的。” 我就非要用 new 一个空对象出来,然后让他在某个地方空指针,反正编译过了就行。是不是一个意思?

    你这样的心态,建议不要写 Java 了,去写某一个什么都给你安排的好好的语言。

  • 資深大佬 : LGA1150

    @Vedar JIT 也会内联方法的,内联了就可以做优化

  • 資深大佬 : no1xsyzy

    同理 Checked exceptions 也一样,Python 不也能正常错误处理吗?
    但为什么还是推荐 Checked exceptions 呢?
    这是协作的问题,不是业务逻辑的问题
    但是,缺乏语法糖也是一个问题。

    另外,入参的问题,Optional 是协变的,所以不会用于入参……

  • 資深大佬 : siweipancc

    舌战群儒:D

  • 資深大佬 : passerbytiny

    不想用 Stream 方式写代码,别说自己会 Java8 。

    自己没见过就说没用,别说自己会 Java 。

  • 資深大佬 : cheng6563

    Java 缺的是个 Notnull 标记而不是 Nullable 标记,这里看 Optional 挺鸡肋的,更不用说 Optional 自己还可能为 null

  • 資深大佬 : masterclock

    在返回要求 Optional 的函数里返回 null 的程序员是不是应该开除?

  • 資深大佬 : PiersSoCool

    如 a.b.c.d.e.f 的时候喜欢用 Optional
    要是 a 我喜欢用 null == a
    怎么方便怎么来

  • 資深大佬 : CosimoZi

    球球你们学点 plt 吧

  • 資深大佬 : qiyuey

    不如 Kotlin 彻底一些

  • 資深大佬 : casillasyi

    @cheng6563 能让 optional 为 null 的,跟写 if (true) 也没区别

  • 資深大佬 : unco020511

    kotlin 的好用

  • 資深大佬 : yl666

    我有个 String 类型的数据,本来想通过用 Optional.ofNullable 来判断是否为空的,结果看了下源码发现它是用 xx == null 来判断的,最后还是用 if 判断吧,其实 Optional 挺好用的,只不过某些场景不太适合

  • 資深大佬 : zhuangzhuang1988

    @lululau 可读性确实低
    而且性能差, 而且可调试不好

  • 資深大佬 : hantsy

    @casillasyi 写法差别很大。
    Optional 流式操作都是假定它不是 Null,如果数据流遇到 Null 的情况走 Else 路线,这和 Scala 中 OPTION,SOME,NULL 类似,Java 8 中要处理 if a= null 情况使用 Optinal 非常容易,代码看起来舒服得多, 在实际项目非常实用。

    下面 Spring 5.2 加入 MVC 加入 Funtional 编程的例子,传统的 Controller 一样可以用。

    https://github.com/hantsy/spring-webmvc-functional-sample/blob/master/java/src/main/java/com/example/demo/DemoApplication.java#L77-L85

    “`java
    public ServerResponse get(ServerRequest req) {
    return this.posts.findById(Long.valueOf(req.pathVariable(“id”)))
    .map(post -> ok().body(post))
    .orElse(notFound().build());
    }
    “`

  • 資深大佬 : hantsy

    @yl666 所有的判断 Null 的情况都是可以用 Optional, 更方便。 你觉得不方便或者不适合,只是思想上还没接受 Stream 方式,缺少 Stream API 使用实践。

  • 資深大佬 : casillasyi

    @hantsy 我觉得他们认为的 optional 本身是 null 的情况是这个对象是 null,而不是 value 为 null

  • 資深大佬 : AxEqaq

    用 guava 的 cache 还是需要用到 optional 判空的

  • 資深大佬 : hantsy

    @casillasyi

    API 设计本来就应该一层层约束的,如果调用别从的 API,返回 Optional,成为规约,而不应该返回是 Null 。

    再说了,Spring 5 内部强制大量使用了 Asserts 工具类, Bean Validation (输入参数)和 JSR 305 (输入,结果等都可以约束) 来保证 API 稳定性。Spring Data 中 findByID 很早就改成返回 Optional, 用了几年,从来没见过返回此处 Optional==Null 的情况。如果有,请帖一些公开的开源的 API 看看。

  • 資深大佬 : casillasyi

    @hantsy 问他们啊。。。

  • 資深大佬 : oneisall8955

    一开始我觉得鸡肋,后来发现是自己姿势不对(=_=)

  • 資深大佬 : oneisall8955

    @huifer 接口定义返回 Optional,默认就是不会返回 null,调用者不用判断是否是 null,如果返回 null,把锅甩给开发这个接口的辣鸡开发

  • 資深大佬 : oneisall8955

    @hantsy 赞同,上说需要 optional == null 都是没理解透彻 optional 的精髓

  • 資深大佬 : hantsy

    @oneisall8955 这个情况在国内可能太多了,因为之前我在上海两个创业项目的经历,现在的年轻开发人员基本敷衍做事的太多,很多基本的代码约束都做不到,要费很多唇舌去要求。

    不知道国内有多少用过 Null Object 模式。但我觉得这应该是一个最基本的问题,可以回避很多 Null 代码检测问题。

    另外,像 Collection 类的使用,从我开始工作时,就看到一些相关的模式(或者叫实践)使用,比如:一个类中有一个 Collection field,应该初始化为一个 EmptyList/Set 等,有方法返回 Collection,永远保证不会返回 Null (没有结果以 Empty List/Set 代替)。

  • 資深大佬 : nnnToTnnn

    Java 基本上好几年没写了,我的 jdk 8 出来的时候, 我依稀记得 optional 是为了解决 a?.b() 的问题,但是由于 Java 是面向对象的语言,这个思想还没怎么转换过来。 所以目前的 optional 应该是为了解决 Stream API 中 a?.b() 的问题,而不是单纯的空指针。

  • 資深大佬 : nnnToTnnn

    例子 这是一个 List 结构
    “`
    {
    user: {
    name: {
    name: {
    name: {
    key: ‘1’
    }
    }
    }
    }

    }

    “`

    以上每一个字段都有可能是空,那么你会先 5 个 if 语句来进行判断,optional 估计是解决这个问题的。

  • 資深大佬 : jewer3330

    吃瓜群众

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具