当前位置: 首页 > Web前端 > vue.js

Java8中Optional类的源码实现与分析

时间:2023-03-31 16:06:06 vue.js

Optional类位于java.util包中,是JDK1.8以来新增的。它是一个final类,不能被继承,构造函数是私有的,不能被实例化,提供了一系列对null和空值的处理方法。它是一个包装类,可以包装非空对象和空值。我们来看看它的定义和默认构造函数。publicfinalclassOptional{privateOptional(){this.value=null;}}众所周知,在Java开发过程中,经常需要对null进行判断和处理。如果错过了,就会抛出NullPointerException,所以Null判断在代码中几乎无处不在,那么神奇的null是怎么来的呢?1965年,一位名叫TonyHoare的英国计算机科学家在设计ALGOLW语言时想到了nullreferences的想法。ALGOLW是最早在堆上分配记录的类型化语言之一。Hoare选择空引用方法“只是因为它很容易实现”。虽然他设计的初衷是“通过编译器的自动检测机制,确保所有使用引用的地方都是绝对安全的”,但他还是决定给空引用开绿灯,因为他认为这是一个“非——存在价值”。“最简单的建模方式。多年后,他开始后悔当初的决定,称其为“我百万的错误”。(引用自网络)其实引入null的目的是为了表示没有变量那么Java8为什么要引入这样一个Optional类呢,主要目的是模拟变量值的存在与否,这样不管变量有没有值,都可以用Optional来表示,可以减少空值的判断逻辑,使代码结构更简单,减少NullPointerException异常的发生。1.构造函数Optional类提供了两个构造函数,都是私有的,如下:privateOptional(){this.value=null;}privateOptional(Tvalue){//value不能为null,否则会抛出Nullpointerexceptionthis.value=Objects.requireNonNull(value);}因为构造函数是private的,Optional类不能直接实例化,那么创建了Optional实例怎么办?可以使用以下三种方法:empty():通过静态工厂方法创建一个空的Optional实例;of():用Optional包返回指定值,如果值为null,抛出NullPointerException异常;ofNullable():用Optional封装指定值并返回。如果值为null,则返回一个空的Optional对象;2.方法Optional类提供了一些方法,主要分为静态方法和实例方法,上面提到的三个方法都是静态方法,主要用来创建Optional实例。2.1静态方法(1)empty()empty()方法是通过静态工厂方法创建一个空的Optional实例,不包含任何值。定义如下:privatestaticfinalOptionalEMPTY=newOptional<>();publicstaticOptionalempty(){@SuppressWarnings("unchecked")Optionalt=(Optional)EMPTY;returnt;}如果直接调用empty()方法,会直接返回静态常量EMPTY。(2)of()of()方法用Optional封装后返回指定值。如果值为null,则抛出NullPointerException。源码如下:publicstaticOptionalof(Tvalue){returnnewOptional<>(value);}直接通过newOptional(Tvalue)方法创建实例。此构造方法使用Objects.requireNonNull()来检查传入的参数。源码如下:publicstaticTrequireNonNull(Tobj){if(obj==null)thrownewNullPointerException();returnobj;}也就是说of()方法不接受空值。(3)ofNullable()ofNullable()方法将指定值封装在一个Optional中并返回。如果值为null,则返回一个空的Optional对象,定义如下:publicstaticOptionalofNullable(Tvalue){returnvalue==null?empty():of(value);}从实现上可以看出,ofNullable()方法可以接受null空值,而of()方法不能接受空值,这也是它不同于of()的原因区分的方法。2.2实例方法(1)get()get()方法用于获取Optional封装的值。如果值存在,则将值封装在Optional中返回,否则抛出NoSuchElementException,定义如下:publicTget(){if(value==null){thrownewNoSuchElementException("Novalue展示”);}returnvalue;}其中value值是Optional中的一个成员变量,定义如下:privatefinalTvalue;(2)isPresent()isPresent()方法用于判断该值是否存在。如果该值存在,则返回true,否则返回false。它的定义如下:publicbooleanisPresent(){returnvalue!=null;}(3)ifPresent()ifPresent()方法也用于判断值是否存在。如果该值存在,则使用该值执行方法调用,否则什么也不做。它的定义如下:publicvoidifPresent(Consumerconsumer){if(value!=null)consumer.accept(value);}这个方法的参数是Consumer。如果该值存在,它将被传递到Consumer.accept()方法中。Consumer类是一个函数式接口,定义如下:@FunctionalInterfacepublicinterfaceConsumer{voidaccept(Tt);默认ConsumerandThen(Consumerafter){Objects.requireNonNull(after);返回(Tt)->{接受(t);后。接受(t);};}}(4)filter()filter()方法主要用于条件过滤。如果该值存在并满足提供的谓词,则返回一个包含该值的Optional对象;否则返回一个空的Optional对象,其定义如下:publicOptionalfilter(Predicatepredicate){//filter方法中的predicate参数不能为空,否则会出现空指针异常被抛出Objects.requireNonNull(predicate);如果(!isPresent())返回这个;否则返回predicate.test(value)?this:empty();}filter()方法的参数需要传入一个Predicate谓词,参数不能为null,否则会抛出NullPointerException,当该值存在时,会调用Predicate.test()方法判断(5)map()map()方法主要是对Optional封装的值执行映射函数。如果该值存在,它会对该值执行提供的映射函数调用。如果该值不存在,则直接返回一个空的Optional对象。定义如下:publicOptionalmap(Functionmapper){//map方法中的参数mapper函数不能为空,否则空指针异常抛出Objects.requireNonNull(映射器);如果(!isPresent())返回空();else{returnOptional.ofNullable(mapper.apply(value));}}(6)flatMap()flatMap()方法主要是对Optional封装的值执行映射函数,如果该值存在,则对该值执行提供的映射函数调用,返回一个Optional类型的值,否则返回一个空的Optional对象,定义如下:publicOptionalflatMap(Function>mapper){//flatMap方法中的参数mapper函数不能为空,否则将抛出空指针异常Objects.requireNonNull(mapper);如果(!isPresent())返回空();else{returnObjects.requireNonNull(mapper.apply(value));flatMap()方法和map()方法有什么区别?方法中定义的参数(7)orElse()或Else()方法主要用于有值直接返回,没有值则返回方法设置的默认值。源码如下:publicTorElse(Tother){returnvalue!=n乌尔?value:other;}(8)orElseGet()orElseGet()方法与orElse()方法类似,只是当没有value时,orElseGet()方法不直接返回值,而是返回一个指定的Supplier接口返回值定义如下:publicTorElseGet(Supplierother){returnvalue!=null?value:other.get();}(9)orElseThrow()orElseThrow()方法,如果没有value,则直接抛出指定Supplier接口产生的异常,定义如下:publicTorElseThrow(SupplierexceptionSupplier)throwsX{//如果value不为null,直接returnif(value!=null){returnvalue;}else{抛出exceptionSupplier.get();}}3.其他相关类除了Optional类之外,java.util包中还提供了其他三个基本类型的Optional类,如下:OptionalIntOptionalLongOptionalDouble这三个类的源码与Optional类似,只是Optional类使用通用定义,它们只能应用于基本数据类型