博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java8学习:Optional的简单使用
阅读量:6715 次
发布时间:2019-06-25

本文共 4840 字,大约阅读时间需要 16 分钟。

内容来自《 java8实战 》,本篇文章内容均为非盈利,旨为方便自己查询、总结备份、开源分享。如有侵权请告知,马上删除。

书籍购买地址:

  • 如下代码

    public class Person {    private Car car;    public Car getCar() {        return car;    }}public class Car {    private Insurance insurance;    public Insurance getInsurance() {        return insurance;    }}public class Insurance{    private String name;    public String getName() {        return name;    }}//将要使用的代码public String getCarInsuranceName(Person person){    return person.getCar().getInsurance().getName();}
  • 如上代码如果使用,如果某个Person没有车,那么就会引发空指针异常,在平常我们使用if来去判断的,比如

    public String getCarInsuranceName(Person person){    if (null != person){        Car car = person.getCar();        if (null != car){            Insurance insurance = car.getInsurance();            if (insurance != null) {                return insurance.getName();            }        }    }    return "UnKnow";}
  • 或者更容易读的是这样的,避免了if的嵌套难以阅读

    public String getCarInsuranceName(Person person){    if (person == null) {        return "UnKnow";    }    Car car = person.getCar();    if (car == null){        return "UnKnow";    }    Insurance insurance = car.getInsurance();    if (insurance == null) {        return "UnKnow";    }    return insurance.getName();}
  • 如上null的解决办法使用中的,并且不容易阅读,java8使用了Optional来解决null问题

markdown_img_paste_20181122155551525

  • Optional只能包含一个对象,对象存在的时候,Optional只是对对象的简单封装,如果没有对象,那么缺失的值被建模成一个空的Optional对象,有方法Optional.empty()返回
  • null和Optional的区别:null一定会触发空指针异常,而Optional.empty()就没有事,因为他是一个有效对象,是Optional 的单一实例.
  • 使用Optional重新定义bean对象

    public class Person {      private Optional
    car; public Optional
    getCar() { return car; }}public class Car { private Optional
    insurance; public Optional
    getInsurance() { return insurance; }}public class Insurance{ private String name; //公司肯定有名字 public String getName() { return name; }}
  • 上面中Person中的car类型是Optional,很明确的表达了Person可能有car对象也可能没有,同样对car的引用做了保证,有car的话就是car对象,没有car 的话就是Optional.empty()
  • Insurance中name并没有加Optional,因为公司肯定是有名字的,如果name为空只能代表参数是错误的,而这里如果加上Optional只能掩盖错误发生

Optional的创建

  • 空对象:Optional.empty()
  • 依靠一个非空对象创建Optional:Optional.of(notnullobj),如果notnullobj是一个空对象,那么就会抛出空指针异常
  • 可接受null对象的Optional:Optional.ofNullable(car),car对象可以是空对象也可以不是空对象,如果是空对象则得到一个空的Optional

使用map从Optional中提取和转换值

String name = null;if (insurance != null){    name = insurance.getName();}
  • 如上是原来的提取的代码,先判断在取值,避免空指针,如下使用Optional

    Optional
    name = Optional.ofNullable(insurance).map(Insurance::getName);
    • map函数会应用于流的每个元素上,然后返回name,可以把Optional看作是一个特殊的集合数据,至多包含一个元素,如果insurance包含值,那么就交给map处理,否则返回空Optional,就什么也不做
  • 本文开头提到的这样一连串的调用,怎么用Optional解决呢?

    //原来public String getCarInsuranceName(Person person){    return person.getCar().getInsurance().getName();}
    • 我们是用如下代码可不可以呢 ?
    public String getCarInsuranceName(Optional
    person){ person.map(Person::getCar) .map(Car::getInsurance) .map(Insurance::getName);}
    • 如上代码是编译通过不了的,因为person对象是一个Optional对象,那么他调用map将会返回一个Optional>,这显然是错误的
    • 之前我们在Stream遇到同样的问题,当时是用flatMap解决的,在这同样适用,如下
    public String getCarInsuranceName(Optional
    person){ return person.flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) .orElse("Unknow");}
    • 如上我们很清楚的就可以知道哪些对象可能是null,并且省去了if语句的平判断,在最后orElse:如果map得到的是null,那么就会有默认的UnKnow替代null,以防止发生空指针

Optional无法序列化

  • 为什么?

    • 如上代码中我们展示了使用Optional去构建bean,将允许缺失或者暂时无定义的变量值用特殊的形式标记出来,但是Optional的设计初衷并不是这样的,它的设计初衷仅仅是要支持能返回Optional的语法,由于它设计时就没有考虑将其作为类的字段使用,所以它也并未实现序列化接口,所以如果在框架或者序列化库中使用了 Optional修饰字段,那么可能会引发错误
    • 但是如上我们看到了,Optional应用到bean中也是不错的,能够清楚的反映出那些字段是有可能为null的,并且可以使用Optional的特性,可以这样在bean中应用Optional
    public class Car {    private Insurance insurance;    public Optional
    getInsuranceAsOptional() { return Optional.ofNullable(insurance); }}

使用filter剔除特定的值

  • 如果需要判断某个公司,那么我们需要这样的判断

    Insurance insurance = ...;if (null != insurance && "lalala".equals(insurance.getName())){            System.out.println("...");}
  • 使用filter方法

    Optional
    insurance = null;insurance.filter(i -> "lalala".equals(i.getName())) .ifPresent(i -> System.out.println("..."));
    • 如上的ifPresent方法是判断i是否是空值,不是空值就执行后面的输出,是空即什么都不做

异常与Optional对象

  • String转换为Integer对象,如果转换错误就会爆数字格式化异常,我们必须try上异常以处理异常
  • 需求:输入参数转换为int,然后返回该转换后的值,出错的话就返回0

    public Integer StringParse(String str){    if (null == str) return 0;    try {        return Integer.parseInt(str);    }catch (NumberFormatException e){        return 0;    }}
  • 用Optional解决

    public Optional
    StringParse(String str){ try { return Optional.of(Integer.parseInt(str)); }catch (NumberFormatException e){ return Optional.empty(); }}

避免使用基本类型的Optional对象

  • 对于之前的函数式接口,我们提到的如果基本类型比较多,那么就优先使用对应的基本类型的函数式接口,比如IntFunction,但是Optional不推荐使用OptionalInt等类似的基本类型对象,因为这些对象中并没有map和filter等方法

转载地址:http://qeelo.baihongyu.com/

你可能感兴趣的文章
bzoj1941[Sdoi2010]Hide and Seek
查看>>
IT兄弟连 Java Web教程 经典面试题2
查看>>
利用setTimeoutc处理javascript ajax请求超时
查看>>
三、Java基础工具(1)_常用类——字符串
查看>>
文献管理与信息分析》第二讲作业
查看>>
java 遍历arrayList的四种方法
查看>>
根据不同的产品id获得不同的下拉选项 (option传多值)
查看>>
css3新增属性:多列(column)
查看>>
redis 主从配置和集群配置
查看>>
手机3D游戏开发:自定义Joystick的相关设置和脚本源码
查看>>
java 数组偶数排在奇数前面
查看>>
window.frames["detailFrm"].isSubmitting = true;//?起什么作用
查看>>
ASCII表
查看>>
idea之debug
查看>>
什么是真正的流程管理?流程管理的是与不是。
查看>>
SEO实践:SEO友好的URL结构
查看>>
洛谷P1613 跑路
查看>>
无论所有题,一定要先分析清楚,所有eade case和逻辑都满足后,再动笔
查看>>
softlayer
查看>>
python各种模块,迭代器,生成器
查看>>