1简介NullPointerException在开发过程中经常会遇到,一不小心就会出现一个小bug。如果可以避免这个问题,Optional就是专门解决这个问题的类,那么Optional怎么用呢?让我们一起探索吧!2源码分析2.1Optional定义Optional类是Java8为了解决空值判断问题而创建的容器类。在java.util下,使用Optional类可以避免显式的空值判断和null导致的NullPointerException。首先,Optional是一个容器,可以容纳T类型的值或者是一个空容器对象。可选容器只能存储一个值。2.2可选属性1)源代码:/***{@codeempty()}的通用实例。*/privatestaticfinalOptional>EMPTY=newOptional<>();/***如果非空,则该值;如果为null,则表示不存在任何值*/privatefinalT值;根据源码可以看到Optional有两个属性,一个是EMPTY表示空值和泛型值;2.3Optional方法Optional除了toString()、hashCode()、equals()等Object方法外,还包括以下方法。2.3.1私有构造函数/***构造一个空实例。**@implNote通常只有一个空实例,{@linkOptional#EMPTY},*每个VM应该存在。*/privateOptional(){this.value=null;}/***用存在的值构造一个实例。**@paramvalue要存在的非空值*@throwsNullPointerExceptionifvalueisnull*/privateOptional(Tvalue){this.value=Objects.requireNonNull(value);}分别是创建一个空实例和用当前值构造一个实例。2.3.2创建方法1)源码publicstaticOptionalempty(){@SuppressWarnings("unchecked")Optionalt=(Optional)EMPTY;returnt;}publicstaticOptionalof(Tvalue){returnnewOptional<>(value);}publicstaticOptionalofNullable(Tvalue){返回值==null?empty():of(value);}2)方法说明empty():创建一个空的Optional实例of(Tt):创建一个Optional实例,当t为null时抛出异常ofNullable(Tt):创建一个Optionalinstance,但是当t为null时不会抛出异常,而是返回一个空的instance3)测试代码publicstaticvoidmain(String[]args){Integervalue1=null;整数值2=1;try{Optionaloptional1=可选。空的();System.out.println("optional1已创建");}catch(Exceptione){System.out.println("optional1failed");}try{Optionaloptional2=Optional.of(value1);System.out.println("optional2已创建");}赶上(除了e){System.out.println("optional2failed");}try{Optionaloptional3=Optional.ofNullable(value1);System.out.println("optional3已创建");}catch(Exceptione){System.out.println("optional3failed");}try{Optionaloptional4=Optional.of(value2);System.out.println("optional4已创建");}catch(Exceptione){System.out.println("optional4failed");}try{Optionaloptional5=Optional.ofNullable(value2);System.out.println("optional5已创建");}catch(Exceptione){System.out.println("optional5failed");}}4)运行结果2.3.3取值方式1)源码publicTget(){if(value==null){thrownewNoSuchElementException("Novaluepresent");}返回值;}2)方法说明get():如果Optional不为空,则返回Optional容器中的值,否则抛出NoSuchElementException3)测试代码publicstaticvoidmain(String[]args){Integervalue1=null;整数值2=1;可选<整数>optional1=Optional.ofNullable(value1);Optionaloptional2=Optional.of(value2);尝试{整数结果=optional1.get();System.out.println("optional1的值为:"+result);}catch(Exceptione){System.out.println("optional1取值失败,原因:"+e.getMessage());}try{Integerresult=optional2.get();System.out.println("optional2的值为:"+result);}catch(异常e){System.out。println("optional2取值失败,原因:"+e.getMessage());}}4)运行结果2.3.4判断方法1)源码publicbooleanisPresent(){returnvalue!=null;}publicvoidifPresent(Consumerconsumer){if(value!=null)consumer.接受(值);}publicTorElse(Tother){返回值!=null?价值:其他;}publicTorElseGet(Supplierot她){返回值!=空?value:other.get();}publicTorElseThrow(SupplierexceptionSupplier)throwsX{if(value!=null){返回值;}else{抛出exceptionSupplier.get();}}2)方法说明isPresent():判断optional是否为空,为空则返回false,否则返回truefunctionorElse(Tother):如果optional不为空,则返回optional中的对象;如果为空,则返回另一个对象orElseGet(Supplierother):如果optional不为空,则返回optional中的对象;如果为null,否则调用其他函数并返回调用结果如果为null,则抛出Supplier函数产生的异常3)测试代码publicstaticvoidmain(String[]args){Integervalue1=null;整数值2=1;可选<整数>optional1=Optional.ofNullable(value1);可选<整数>optional2=Optional.of(value2);try{if(optional1.isPresent()){System.out.println("optional1的isPresent结果不为空");}else{System.out.println("optional1的isPresent结果为空");}}catch(Exceptione){System.out.println("optional1的isPresent失败,原因:"+e.getMessage());}try{if(optional2.isPresent()){System.out.println("optional2的isPresent结果不为空");}else{System.out.println("optional2的isPresent结果为空");}}catch(异常e){System.out.println("optional2的isPresent判断为空失败,原因:"+e.getMessage());}optional1.ifPresent(t->{inti=t+1;System.out.println("optional1处理后的值为"+i);});optional2.ifPresent(t->{inti=t+1;System.out.println("optional2处理后的值为"+i);});整数值3=2;整数结果=optional1.orElse(value3);System.out.println("optional1执行orElse处理后的值为"+result);结果=optional2.orElse(value3);System.out.println("optional2执行orElse处理后值为"+result);结果=optional1.orElseGet(()->newInteger(-1));System.out.println("optional1执行orElseGet后的值为"+result);结果=可选2。orElseGet(()->新整数(-1));System.out.println("optional2执行orElseGet处理后的值为"+result);try{result=optional1.orElseThrow(()->newRuntimeException("值为空"));System.out.println("optional1执行orElseThrow处理后的值为"+resul吨);}catch(Exceptione){System.out.println("optional1的orElseThrow抛出异常:"+e.getMessage());}try{result=optional2.orElseThrow(()->newRuntimeException("值为空"));System.out.println("optional2执行orElseThrow处理后的值为"+result);}catch(Exceptione){System.out.println("optional2的orElseThrow抛出异常:"+e.getMessage());4)运行结果2.3.5Filter方法1)源码publicOptionalfilter(Predicatepredicate){Objects.requireNonNull(predicate);如果(!isPresent())返回这个;否则返回predicate.test(value)?this:empty();}2)方法说明filter(Predicatep):如果optional不为空,则执行Predicatep,如果p的结果为真,则返回原来的optional,否则返回空optional3)测试代码publicstaticvoidmain(String[]args){整数值1=5;整数值2=6;可选<整数>optional1=Optional.ofNullable(value1);可选<整数>optional2=Optional.of(value2);可选<整数er>result=optional1.filter(t->t>5);System.out.println("optional1过滤器后的值:"+result);结果=optional2.filter(t->t>5);System.out.println("optional2过滤后的值:"+result);4)运行结果2.3.6映射方法1)源码publicOptionalmap(Functionmapper){Objects.requireNonNull(mapper);如果(!isPresent())返回空();else{returnOptional.ofNullable(mapper.apply(value));}}publicOptionalflatMap(Function>mapper){Objects.requireNonNull(mapper);如果(!isPresent())返回空();else{returnObjects.requireNonNull(mapper.apply(value));}}2)方法描述map(Functionmapper):如果有值,则对其应用提供的映射函数,如果结果非空,则返回一个描述结果的Optional,否则返回一个空的Optional.flatMap(Functionmapper):如果有一个值,将提供的可选映射函数应用到它,返回结果,否则返回一个空的可选函数。此方法类似于map(Function),但提供的映射器的结果已经是一个Optional,如果调用,flatMap不会用额外的Optional包装它。区别:map会自动把u放入optional,而flatMap需要手动为u创建一个optional3)测试代码publicstaticvoidmain(String[]args){Useruser1=null;Useruser2=newUser("用户名",19);可选<用户>optional1=Optional.ofNullable(user1);可选<用户>optional2=Optional.of(user2);System.out.println("=========地图===========");System.out.println("optional1的map前的值:"+optional1);Optional结果=optional1.map(t->t.getName());System.out.println("optional1的map后的值:"+result);System.out.println("optional2的map前的值:"+optional2);result=optional2.map(t->t.getName());System.out.println("optional2的map后的值:"+result);System.out.println("============flatMap========");System.out.println("optional1的flatMap前的值:"+optional1);可选<整数>result2=optional1.flatMap(t->Optional.ofNullable(t.getAge()));System.out.println("optional1的flatMap后的值:"+result2);System.out.println("optional2的flatMap前的值:"+optional2);result2=optional2.flatMap(t->Optional.ofNullable(t.getAge()));System.out.println("optional2的flatMap后的值:"+result2);}公共类用户{字符串名称;整数年龄;publicUser(Stringname,Integerage){this.name=name;这个。年龄=年龄;}publicStringgetName(){返回名称;}publicIntegergetAge(){returnage;4)运行结果3应用实例3.1错误用法由于Optional没有实现Serializable接口,所以不能作为类的属性使用。不要将Optional用作方法的参数。直接把if(x!=null)换成Optional.ofNullable(x).isPresent(),疑似过度编码。直接使用Optional.get()的返回值进行操作,Stringresult=Optional.ofNullable(null).get().toString();这仍然会抛出异常。3.2建议用法A类有B类属性,B类有C类属性,C类有字段名。使用前Optional:if(atest!=null){Btestbtest=atest.getBtest();if(btest!=null){Ctestctest=btest.getCtest();如果(ctest!=null){名称=ctest。获取名称();使用Optional后:name=Optional.ofNullable(atest).map(t->t.getBtest()).map(t->t.getCtest()).map(t->t.getName()).orElse("默认值");代码看起来更干净吗?4小结通过分析Optional的源码和用例测试代码的运行结果可以看出,使用Optional可以优化空值判断的代码,使代码更加优雅整洁。作者:陈昌浩