java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java8中Optional操作

Java8中Optional操作的实际应用

作者:汤圆学Java

Optional类是一个可以为null的容器对象,如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象,下面这篇文章主要给大家介绍了关于Java8中Optional操作实际应用的相关资料,需要的朋友可以参考下

简介

目的:Optional的出现主要是为了解决null指针问题,也叫NPE(NullPointerException)

外形:Optional外形酷似容器(其实它就是一个容器),只是这个容器比较特殊,因为它只能存放一个对象,运气不好的话这个对象还是个null

操作:Optional从操作上来看,又跟前面的Stream流式操作很像,比如过滤filter - 提取map等

下面我们用比较简单的例子来对比着看下,Optional的一些基础用法

正文

1. Optional是什么

Optional是一个容器,只能存放一个对象(可为null)

Optional的出现是

2. 没它 VS 有它

下面我们用旧代码和新代码来对比着看(所谓的新旧是以Java8为分割线)

案例1:现有C类,我们要提取C.name属性

public class OptionalDemo {
    private static final String DEFAULT_NAME = "javalover";

    public static void main(String[] args) {
      // 传入null,以身试法  
      getName(null);
    }
    // 取出c.name
    public static void getName(C c){
        // 旧代码 Java8之前
        String name = (c!=null ? c.getName() : DEFAULT_NAME);
        System.out.println("old: "+name);
        // 新代码 Java8之后(下面的三个操作方法后面会介绍,这里简单了解下)
        String nameNew = Optional
            				// 工厂方法,创建Optional<C>对象,如果c为null,则创建空的Optional<C>对象
                            .ofNullable(c)
            				// 提取name,这里要注意,即使c==null,这里也不会抛出NPE,而是返回空的Optional<String>,所以在处理数据时,我们不需要担心空指针异常
                            .map(c1->c1.getName())
            				// 获取optional的属性值,如果为null,则返回给定的实参DEFAULT_NAME
                            .orElse(DEFAULT_NAME);

        System.out.println("new: "+nameNew);
    }
}
class C{
    private String name;

    public C(String name) {
        this.name = name;
    }
  // 省略getter/setter
}

乍一看,好像Java8之前的旧代码更合适啊,只需要一个三目运算符

再看Optional操作,发现并没有那么简洁

是这样的,如果只是一层判断,那普通的if判断做起来更方便;

但是如果嵌套两层呢,比如b.getC().getName()?

下面我们就看下,两层嵌套会怎么样

例子2:现多了一个B类(依赖C类),我们要从对象B中提取C的属性name,即b.getC().getName()

public static void getName2(B b){
        // 旧代码
        String name = (b!=null ? ( b.getC()!=null ? b.getC().getName() : DEFAULT_NAME) : DEFAULT_NAME);
        // 新代码
        String nameNew = Optional
                .ofNullable(b)
                .map(b1->b1.getC())
                .map(c1->c1.getName())
                .orElse(DEFAULT_NAME);
        System.out.println(nameNew);
    }

class B{
    private C c;

    public B(C c) {
        this.c = c;
    }
  // 省略getter/setter
}

这次不管是乍一看,还是一直看,都是Optional更胜一筹

例子3:现多了一个A类(依赖B类),我们要提取a.getB().getC().getName()

等等等,省略号

意思到就行,反正要说的就是单从判空来看的话,Optional肯定是好过三目运算符的(if/else这里就不举了,它的嵌套只会更多)

3. 核心操作

因为Optional主要是操作数据(类似数据库操作),所以我们这里从数据的角度来进行分析

这里我们可以分为三种操作:保存数据、处理数据、获取数据

保存数据

处理数据

获取数据

上面这些操作中,不常用的就是get()和empty()

其他的就不举了,这里主要说下map()和flatMap()

如下图所示:

map()主要是提取Optional中的属性C的属性name,然后再包装到新的Optional

输入Optional<C>, 输出Optional<String>(即Optional<c.name>)

String nameNew = Optional
                    .ofNullable(c)
                    .map(c1->c1.getName())
                    .orElse("xxx");

flatMap()主要是提取Optional中的属性B的Optional<C>属性中的C的值,然后再包装到新的Optional

输入Optional<B>,输出Optional<C>

public class FlatMapDemo {
    private static final String DEFAULT_NAME = "javalover";

    public static void main(String[] args) {
        getName(null);
    }

    // 取出 b.c.name
    public static void getName(B b){
        C c = Optional
                .ofNullable(b)
            	// 这里扁平化处理,提取Optional<C>中的C
            	// 如果用map,则返回的是Optional<Optional<C>>
                .flatMap(b->b.getC())
                .orElse(new C("xxx"));
        System.out.println(c.getName());
    }
}

class B{
    private Optional<C> c;

    public Optional<C> getC() {
        return c;
    }

    public void setC(C c) {
        this.c = Optional.ofNullable(c);
    }
}

class C{
    private String name;

    public C(String name) {
        this.name = name;
    }
    // 省略getter/setter
}

4. 应用

从规范角度来讲,是为了代码清晰,一看用Optional<T>变量,就知道T可能为null;

从编码角度来讲,主要是应用在非空判断;但是实际场景的话,有两个

// 取出c.name
public static void getName(C c){
    // 自己手动包装 Optional<C>
    String nameNew = Optional
        .ofNullable(c)
        .map(c1->c1.getName())
        .orElse(DEFAULT_NAME);

    System.out.println("new: "+nameNew);
}
// 返回Optional<Car>,通过.orElse(defaultCar)就可以获取返回值,如果返回值为null,还可以设定一个默认值defaultCar
Optional<Car> selectOne(SelectStatementProvider selectStatement);

总结

总结

到此这篇关于Java8中Optional操作的文章就介绍到这了,更多相关Java8中Optional操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文