Optional类隶属于java。util包中 Optional类是一个可以为null的容器对象,它的出现很好的解决空指针异常。 简而言之,这个类的出现,相当于Java8提供了一个封装好的容器,在使用的时候可以放心大胆的处理null的逻辑或异常。需要把值放入容器中,后续的取值操作和其他逻辑,使用其提供的Api即可方便简单的处理null指针的情况。 Optional类的源码数量并不多,有时间还是可以看看的,先看看3个初始化容器内容的静态方法,(empty,of,ofNullable),由于所有构造函数都是private的,所以只能使用工厂方法来获取Optional的实例 在类中第一行便是定义了一个静态常量EMPTY,泛型的使用的是通配符?,意思是可以传入任意类型,并赋值为空参构造实例,第二行定义为final的value,则是用于存储放入容器中的值Commoninstancefor{codeempty()}。privatestaticfinalO?EMPTYnewOptional();Ifnonnull,ifnull,indicatesnovalueispresentprivatefinalTprivateOptional(){this。}静态方法empty 这个方法作用很简单,就是将类加载时初始化的EMPTY静态常量强转成传入的泛型T,然后返回强转后的值,可以调用该方法返回一个值为null的Optional容器publicstaticTOptionalTempty(){SuppressWarnings(unchecked)OptionalTt(OptionalT)EMPTY;} 使用方式,声明一个value类型为String的空容器OptionalStringemptyOptional。empty();静态方法of 这个方法相当于要求传入一个值,该值会做为容器中的值,调用顺序是传入值后,调用Optional的构造方法,而构造方法会调用Objects。requireNonNull方法去判断传入的值是否为空,如果为空则直接抛出空指针异常NullPointerException,不为空则返回值并赋值给成员属性valuepublicstaticTOptionalTof(Tvalue){returnnewOptional(value);}privateOptional(Tvalue){this。valueObjects。requireNonNull(value);} 构造函数中调用的Objects类的requireNonNull方法publicstaticTTrequireNonNull(Tobj){if(objnull)thrownewNullPointerException();} 使用方式,声明一个容器,并且值为123,通过实例方法get可以获取出使用of方法初始化的值OptionalIntegeraOptional。of(123);Integerintegera。get();静态方法ofNullable 这个方法逻辑比较简单,判断传入的值是否为空,为空则调用上面说的empty方法,不为空则调用上面说的of方法publicstaticTOptionalTofNullable(Tvalue){returnvaluenull?empty():of(value);}下面看看一些实例方法是怎么实现的get方法 在of方法中演示过用法了,其作用就是返回当前容器中value的值,如果为value为空则直接抛出NoSuchElementException异常publicTget(){if(valuenull){thrownewNoSuchElementException(Novaluepresent);}}isPresent方法 判断当前容器中value的值是否为空,并返回一个boolean值publicbooleanisPresent(){returnvalue!} 使用:先判断值是否为空,如果为空直接调用get方法会报错if(optional。isPresent()){poptional。get();}ifPresent方法 判断当前容器中value的值是否为空,空则什么都不做,不为空则将value传入Consumer的accept中执行publicvoidifPresent(C?superTconsumer){if(value!null)consumer。accept(value);} java。util。function。Consumer是JDK提供的函数接口,包含了一个无返回值的带参的方法:voidaccept(Tt),传入一个泛型类型的参数并执行一些操作。由于这是一个函数式接口,可以使用传统的匿名内部类编写,也可以使用Lambda表达式,函数接口和Lambda表达式在这里不再赘述FunctionalInterfacepublicinterfaceConsumerT{Performsthisoperationonthegivenargument。paramttheinputargumentvoidaccept(Tt);} 使用:分别采取了匿名内部类和lambda表达式的方式编写,由于value不为null,所以都会执行accept方法并输出test字符串OptionalStringdataOptional。of(test);data。ifPresent(newConsumerString(){Overridepublicvoidaccept(Strings){System。out。println(s);}});data。ifPresent(System。out::println);orElse方法 判断当前容器中value的值是否为空,不为空则返回value,空则返回传入的值publicTorElse(Tother){returnvalue!null?value:} 使用:由于容器中的值为空,所以会返回test字符串OptionalStringemptyOptional。empty();System。out。println(empty。orElse(test));orElseGet方法 判断当前容器中value的值是否为空,不为空则返回value,空则调用Supplier实例的get方法,?extendsT的作用为返回值类型只能是T类型或T的子类型publicTorElseGet(S?extendsTother){returnvalue!null?value:other。get();} java。util。function。Supplier是JDK提供的函数接口,包含了一个无参的方法:Tget(),用来返回一个泛型参数指定类型的对象FunctionalInterfacepublicinterfaceSupplierT{Getsaresult。returnaresultTget();} 使用:分别采取了匿名内部类和lambda表达式的方式编写,由于value的值为null,所以最终返回值都是Supplier实例的get方法返回值OptionalStringemptyOptional。empty();Stringanonymityempty。orElseGet(newSupplierString(){OverridepublicStringget(){}});Stringlambdaempty。orElseGet(()lambda);System。out。println(anonymity);System。out。println(lambda);输出两行字符串,anonymity和lambdaorElseThrow方法 和orElseGet类似,泛型函数的泛型作用为返回值类型只能是Throwable类型或Throwable的子类型,如果值为空,则直接抛出一个异常publicXextendsThrowableTorElseThrow(S?extendsXexceptionSupplier)throwsX{if(value!null){}else{throwexceptionSupplier。get();}} 使用:分别采取了匿名内部类和lambda表达式的方式编写,由于value的值为null,所以最终返回值都是Supplier实例的get方法返回值,可以直接往上抛异常或者trycatch捕获处理,这段代码执行后便会抛出任意一个异常publicstaticvoidmain(String〔〕args)throwsException{OptionalObjectemptyOptional。empty();这段注释掉则抛出后面的lambda表达式返回的异常empty。orElseThrow(newSupplierException(){OverridepublicIllegalArgumentExceptionget(){returnnewIllegalArgumentException(valueisnull,fromanonymity);}});这段注释掉则抛出匿名内部类返回的异常empty。orElseThrow((SupplierException)()newIllegalArgumentException(valueisnull,fromlambda));}map方法 首先判断参数mapper是否为空,空则抛出空指针异常,再判断当前容器中value的值是否为空,空则调用empty方法,不为空则返回ofNullable方法的返回值,ofNullable的参数为mapper的返回值,mapper类型为Function类型,和上面讲过的Supplier类似,作用就是如果值不为空,可以执行一个函数进行二次逻辑数据处理并返回。这个mapper函数有两个泛型T和U,T是定义在Optional类名上的,public后面紧跟的作用是声明这个方法有一个泛型U(声明为泛型方法),Function的泛型参数则限定了第一个参数为T类型或T的父类型,第二个参数为U类型或U的子类型publicUOptionalUmap(F?superT,?extendsUmapper){Objects。requireNonNull(mapper);if(!isPresent())returnempty();else{returnOptional。ofNullable(mapper。apply(value));}} java。util。function。Function是JDK提供的函数接口,方法applay的作用就是传入一个值,返回另一个值FunctionalInterfacepublicinterfaceFunctionT,R{Appliesthisfunctiontothegivenargument。paramtthefunctionargumentreturnthefunctionresultRapply(Tt);} 使用:分别采取了匿名内部类和lambda表达式的方式编写,由于value的值不为空,两个变量接受的Optional实例中的值都为3OptionalStringdataOptional。of(test);OptionalIntegerintegerdata。map(newFunctionString,Integer(){OverridepublicIntegerapply(Strings){returns。length()3?1:0;}});OptionalIntegerinteger2data。map(ss。length()3?1:0);System。out。println(integer。get());System。out。println(integer2。get());输出两行字符串3flatMap方法 首先判断参数mapper是否为空,空则抛出空指针异常,再判断当前容器中value的值是否为空,空则调用empty方法,不为空则调用Objects。requireNonNull函数的返回值,将mapper。apply返回值传入,如果apply方法的返回值为空则会抛出异常,使用的方法与map非常类似,唯一区别是map返回值会被调用ofNullable方法进行容器包装,而flatMap要求直接返回Optional容器publicUOptionalUflatMap(F?superT,OptionalUmapper){Objects。requireNonNull(mapper);if(!isPresent())returnempty();else{returnObjects。requireNonNull(mapper。apply(value));}} 使用:分别采取了匿名内部类和lambda表达式的方式编写,使用匿名内部类编写的applay方法返回了一个值为数字1的容器,可调用get输出,使用lambda表达式编写的因为执行Objects。requireNonNull(null)所以抛出异常OptionalStringdataOptional。of(test);OptionalIntegerintegerdata。flatMap(newFunctionString,OptionalInteger(){OverridepublicOptionalIntegerapply(Strings){returnOptional。of(1);}});System。out。println(integer。get());输出字符串1data。flatMap(snull);执行到这里就会抛出异常,因为调用了Objects。requireNonNull(null)filter方法 首先判断参数predicate是否为空,空则抛出空指针异常,再判断当前容器中value的值是否为空,空则返回当前实例,不为空则返回一个三元表达式,会将当前容器的值传入predicate。test函数中,返回一个boolean值,如果true则返回当前实例,否则调用empty函数返回一个空容器,作用就是过滤筛选值。Predicate也是一个函数接口。publicOptionalTfilter(P?superTpredicate){Objects。requireNonNull(predicate);if(!isPresent())elsereturnpredicate。test(value)?this:empty();} java。util。function。Predicate是JDK提供的函数接口,方法test的作用就是传入一个值,返回一个boolean值FunctionalInterfacepublicinterfacePredicateT{Evaluatesthispredicateonthegivenargument。paramttheinputargumentreturn{codetrue}iftheinputargumentmatchesthepredicate,otherwise{codefalse}booleantest(Tt);} 使用:分别采取了匿名内部类和lambda表达式的方式编写,由于rightly的value值不为空,会输出test,而falsely。get()则会抛出异常OptionalStringdataOptional。of(test);OptionalStringrightlydata。filter(newPredicateString(){Overridepublicbooleantest(Strings){returns。equals(test);}});OptionalStringfalselydata。filter(ss。equals());System。out。println(rightly。get());System。out。println(falsely。get());会先输出一次test然后falsely。get时就会抛出异常,因为value为null至此,Optional类中所有的方法和逻辑都阅读完了,源码清晰简单,阅读一遍明白其中的逻辑,对该工具类的使用会有一定的帮助。:)