java8中Optional使用

发布时间:2026/11/5 3:42:14
java8中Optional使用 一、前言在Java中对一个空对象进行操作时便会抛出最常见的异常NullPointerException。为了改善这个问题Java 8中提供了一个java.util.Optional类型。Optional类的Javadoc描述如下这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true调用get()方法会返回该对象。下面介绍Optional类的使用方法。我们县创建好测试实体Address.javaDatapublicclassAddress{privateStringprovince;privateStringcity;privateStringarea;}User.javaDatapublicclassUser{privateStringname;privateStringphone;privateAddressaddress;}二、创建Optional2.1 创建一个空的Optional我们可以使用静态工厂方法Optional.empty创建一个空的Optional对象OptionalUseruserOptional.empty();2.2 根据非空值创建Optional我们也可以使用静态工厂方法Optional.of来创建一个非空对象的Optional对象OptionalUseruserOptional.of(user);如果user为空这段代码会立即抛出一个NullPointerException。2.3 创建可以为null的Optional使用静态工厂方法Optional.ofNullable我们可以创建一个允许null值的Optional对象OptionalUseruserOptional.ofNullable(user);如果user为空对其调用get方法将抛出NoSuchElementException。三、Optional方法3.1 Optional(T value),empty(),of(T value),ofNullable(T value)这四个函数之间具有相关性因此放在一组进行记忆。先说明一下Optional(T value)即构造函数它是private权限的不能由外部调用的。其余三个函数是public权限供我们所调用。那么Optional的本质就是内部储存了一个真实的值在构造的时候就直接判断其值是否为空。那么**of(T value)**的源码如下publicstaticTOptionalTof(Tvalue){returnnewOptional(value);}也就是说of(T value)函数内部调用了构造函数。根据构造函数的源码我们可以得出两个结论:通过of(T value)函数所构造出的Optional对象当Value值为空时依然会报NullPointerException。 通过of(T value)函数所构造出的Optional对象当Value值不为空时能正常构造Optional对象。除此之外呢Optional类内部还维护一个value为null的对象大概就是长下面这样的publicfinalclassOptionalT{//省略....privatestaticfinalOptional?EMPTYnewOptional();privateOptional(){this.valuenull;}//省略...publicstaticTOptionalTempty(){SuppressWarnings(unchecked)OptionalTt(OptionalT)EMPTY;returnt;}}那么empty的作用就是返回EMPTY对象。好了铺垫了这么多可以说ofNullable(T value)的作用了上源码publicstaticTOptionalTofNullable(Tvalue){returnvaluenull?empty():of(value);}好吧大家应该都看得懂什么意思了。相比较of(T value)的区别就是当value值为null时of(T value)会报NullPointerException异常ofNullable(T value)不会throw ExceptionofNullable(T value)直接返回一个EMPTY对象。那是不是意味着我们在项目中只用ofNullable函数而不用of函数呢?不是的一个东西存在那么自然有存在的价值。当我们在运行过程中不想隐藏NullPointerException。而是要立即报告这种情况下就用Of函数。但是不得不承认这样的场景真的很少。博主也仅在写junit测试用例中用到过此函数。3.2 orElse(T other)orElseGet(Supplier? extends T other)和orElseThrow(Supplier? extends X exceptionSupplier)这三个函数放一组进行记忆都是在构造函数传入的value值为null时进行调用的。orElse和orElseGet的用法如下所示相当于value值为null时给予一个默认值:Testpublicvoidtest(){Userusernull;userOptional.ofNullable(user).orElse(createUser());userOptional.ofNullable(user).orElseGet(()-createUser());}publicUsercreateUser(){UserusernewUser();user.setName(zhangsan);returnuser;}这两个函数的区别当user值不为null时orElse函数依然会执行createUser()方法而orElseGet函数并不会执行createUser()方法大家可自行测试。至于orElseThrow就是value值为null时,直接抛一个异常出去用法如下所示Userusernull;Optional.ofNullable(user).orElseThrow(()-newException(用户不存在));3.3 map(Function? super T, ? extends U mapper)和flatMap(Function? super T, Optional mapper)这两个函数放在一组记忆这两个函数做的是转换值的操作。publicfinalclassOptionalT{//省略....publicUOptionalUmap(Function?superT,?extendsUmapper){Objects.requireNonNull(mapper);if(!isPresent())returnempty();else{returnOptional.ofNullable(mapper.apply(value));}}//省略...publicUOptionalUflatMap(Function?superT,OptionalUmapper){Objects.requireNonNull(mapper);if(!isPresent())returnempty();else{returnObjects.requireNonNull(mapper.apply(value));}}}这两个函数在函数体上没什么区别。唯一区别的就是入参map函数所接受的入参类型为Function? super T, ? extends U而flapMap的入参类型为Function? super T, Optional。在具体用法上对于map而言如果User结构是下面这样的publicclassUser{privateStringname;publicStringgetName(){returnname;}}这时候取name的写法如下所示StringcityOptional.ofNullable(user).map(u-u.getName()).get();对于flatMap而言:如果User结构是下面这样的publicclassUser{privateStringname;publicOptionalStringgetName(){returnOptional.ofNullable(name);}}这时候取name的写法如下所示StringcityOptional.ofNullable(user).flatMap(u-u.getName()).get();3.4 isPresent()和ifPresent(Consumer? super T consumer)这两个函数放在一起记忆isPresent即判断value值是否为空而ifPresent就是在value值不为空时做一些操作。这两个函数的源码如下publicfinalclassOptionalT{//省略....publicbooleanisPresent(){returnvalue!null;}//省略...publicvoidifPresent(Consumer?superTconsumer){if(value!null)consumer.accept(value);}}需要额外说明的是大家千万不要把if(user!null){// TODO: do something}给写成UseruserOptional.ofNullable(user);if(Optional.isPresent()){// TODO: do something}因为这样写代码结构依然丑陋。博主会在后面给出正确写法至于ifPresent(Consumer? super T consumer)用法也很简单如下所示Optional.ofNullable(user).ifPresent(u-{// TODO: do something});3.5 filter(Predicate? super T predicate)publicfinalclassOptionalT{//省略....Objects.requireNonNull(predicate);if(!isPresent())returnthis;elsereturnpredicate.test(value)?this:empty();}filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤如果包含的值满足条件那么还是返回这个 Optional否则返回 Optional.empty。OptionalUseruser1Optional.ofNullable(user).filter(u-u.getName().length()6);如上所示如果user的name的长度是小于6的则返回。如果是大于6的则返回一个EMPTY对象。四、实战使用4.1 例1在函数方法中以前写法publicStringgetCity(Useruser)throwsException{if(user!null){if(user.getAddress()!null){Addressaddressuser.getAddress();if(address.getCity()!null){returnaddress.getCity();}}}thrownewExcpetion(取值错误);}JAVA8写法publicStringgetCity(Useruser)throwsException{returnOptional.ofNullable(user).map(u-u.getAddress()).map(a-a.getCity()).orElseThrow(()-newException(取指错误));}4.2 例2比如在主程序中以前写法if(user!null){dosomething(user);}JAVA8写法Optional.ofNullable(user).ifPresent(u-{dosomething(u);});4.3 例3以前写法publicUsergetUser(Useruser)throwsException{if(user!null){Stringnameuser.getName();if(zhangsan.equals(name)){returnuser;}}else{usernewUser();user.setName(zhangsan);returnuser;}}JAVA8写法publicUsergetUser(Useruser){returnOptional.ofNullable(user).filter(u-zhangsan.equals(u.getName())).orElseGet(()-{Useruser1newUser();user1.setName(zhangsan);returnuser1;});}

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询