Optional类

Optional类

Optional类是一个容器类,代表一个值存在和不存在,原来用不惯null表示一个值的不存在,现在用Optional可以更好的表达这个概念;是Java1.8之后解决null值判断问题。

常用方法列表

method desc
Optional.of(T t) 创建一个非空值的Optional实例
Optional.empty() 创建一个空的Optional实例
Optional.ofNullable(T t) 若t不为null,创建Optional实例,否则创建空实例
isPresent() 判断是否包含值
ifPresent(Consumer c) 如果存在值,则使用该值调用指定的消费者,否则不执行任何操作
get() 如果 Optional中有值,返回值,否则抛出 NoSuchElementException
orElse(T t) 如果对象包含值,返回该值,否则返回t
orElseGet(Supplier s) 如果对象包含值,返回该值,否则返回s中获取的值
orElseThrow(Supplier s) 如果容器为空,返回自定义异常信息
filter(Predicate p) 断言型接口返回true,则返回Optional描述的值;否则返回Optional.empty()
map(Function f) 如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
flatmap(Function mapper) 与map类似,返回值要求必须是Optional

引入

看一下下面的代码,为了避免空指针异常,我们需要多层的if判断,不利于代码的易读性同时也不利于书写。

    if (people != null) {
        Country country = people.getCountry();
        if (country != null) {
            City city = country.getCity();
            if (city != null) {
                Street street = city.getStreet();
                if (street != null) {
                    String streetName = street.getStreetName();
                }
            }
        }
    }

创建实例方式

  • Optional.of(T t)

        public void test02() {
            Optional p = Optional.of(new People());
            People people = p.get();
        }
    

    Optional.of(null),无法创建实例,导致NullPointerException

  • Optional.empty()

        public void test03() {
            Optional p = Optional.empty();
            People people = p.get();
        }
    

    创建Optional的空实例,若使用p.get()获取对象,会导致java.util.NoSuchElementException: No value present

  • Optional.ofNullable(T t)

        public void test04() {
            Optional p = Optional.ofNullable(new People());
    
            People people = p.get();
            System.out.println(people);
        }
    

    使用Optional.ofNullable构建Optional实例时,参数可以为其他实例,也可以为null,如果为null时,默认返回的是Optional.empty

          // 源码
        public static  Optional ofNullable(T value) {
            return value == null ? empty() : of(value);
        }
    

获取Optional的值

    public void test04() {
        Optional p = Optional.ofNullable(new People());

        People people = p.get();
        System.out.println(people);
    }

Optional容器类通过get()方法获取容器中的对象,但若是Optional是个空实例,就会发生NoSuchElementException异常,所以Optional容器类提供了isPresent()方法来判断Optional是否是空实例。

    public void test04() {
        Optional p = Optional.ofNullable(new People());

        if (p.isPresent()) {
            People people = p.get();
            System.out.println(people);
        }
    }
    public void test05() {
        String name = "zhangsan";
        Optional optional = Optional.ofNullable("zhangsan");

        Assert.assertTrue(optional.isPresent());

        Assert.assertEquals(name, optional.get());
    }

检查Optional容器类是否有值另外一个方法ifPresent(Consumer c); 如果有值则调用消费者代码块,否则不执行任何操作。若有值而Consumer为空,则会导致NullPointerException

    public void test06() {
        Optional optional = Optional.ofNullable("zhangsan");
        optional.ifPresent(System.out::println);
    }

兜底函数

兜底函数可以理解为默认值,当Optional容器中没有值,则会返回兜底函数的值,避免获取不到值的情况

orElse(T t)

如果对象包含值,返回该值,否则返回t (注意:返回的是具体的值,而不是Optional容器类)

    public void test07() {
        String name = null;
        String username = Optional.ofNullable(name).orElse("zhangsan");

        Assert.assertEquals("zhangsan", username);
    }

orElseGet(Supplier s)

如果对象包含值,返回该值,否则执行Supplier代码块

public void test08() {
    String name = null;
    People people = new People("zhangsan", 18, null);
    String username = Optional.ofNullable(name).orElseGet(people::getName);

    Assert.assertEquals("zhangsan", username);
}

orElse和orElseGet对比

若传入的值为null时

    @Test
    public void test09() {
        System.out.println("orElse");
        String name1 = (String) Optional.ofNullable(null).orElse(getName());

        System.out.println("orElseGet");
        String name2 = (String) Optional.ofNullable(null).orElseGet(() -> getName());
    }

    public String getName() {
        System.out.println("getName");
        return "zhangsan";
    }

结果输出

orElse
getName
orElseGet
getName

可以看出,两者并没有差异,都会调用getName()方法

若传入非null值

    public void test10() {
        System.out.println("orElse");
        String name1 = (String) Optional.ofNullable("lisi").orElse(getName());

        System.out.println("orElseGet");
        String name2 = (String) Optional.ofNullable("lisi").orElseGet(() -> getName());
    }

结果输出

orElse
getName
orElseGet

若传入非null值时,orElse()还是会调用getName(),而orElseGet()则不会执行。

在密集型调用,或者需求量较大时,两者性能上的差异显而易见。

orElseThrow(Supplier s)

如果Optional容器为空,可以返回自定义的异常信息

    public void test11() {
        Object o = Optional.ofNullable(null).orElseThrow(IllegalArgumentException::new);
    }

值过滤

filter(Predicate p)

通过filter(Predicate p)方法过滤出来符合要求的值,其中当断言型接口p返回true,则返回Optional描述的值;否则返回空的Optional

    public void test12() {
        People p = new People("zhangsan", 11, null);
        Optional people = Optional.ofNullable(p)
                .filter(x -> x.getAge() == 11);

        Assert.assertTrue(people.isPresent());
    }

值转换

map()

如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty();

    public void test13() {
        People p = new People("zhangsan", 11, null);

        Optional optionalS = Optional.ofNullable(p).map(x -> x.getName());

        Assert.assertTrue(optionalS.isPresent());
        
        Assert.assertEquals("zhangsan", optionalS.get());
    }

flatmap(Function mapper)

与map类似,返回值要求必须是Optional

    public void test14() {
        People p = new People("zhangsan", 11, null);

        Optional optionalS = Optional.ofNullable(p).flatMap(x -> Optional.ofNullable(x.getName()));

        Assert.assertTrue(optionalS.isPresent());

        Assert.assertEquals("zhangsan", optionalS.get());
    }

总结

链式编程

filter,map,fliterMap返回都是Optional描述的值,所以就可以使用链式编程

    public void test15() {
        People p = null;

        String str = Optional.ofNullable(p)
                .filter(x -> x.getName() != null)
                .flatMap(x -> Optional.ofNullable(x.getName()))
                .orElse("lisi");

        Assert.assertEquals(str, "lisi");
    }

引入的优化

// 每个属性值都是用Optional封装
private Optional country;
    public void test20() {
        People p = null;
        String s = Optional.ofNullable(p)
                .flatMap(x -> x.getCountry())
                .flatMap(x -> x.getCity())
                .flatMap(x -> x.getStreet())
                .map(x -> x.getStreetName())
                .orElse("北京东路");

        Assert.assertEquals("北京东路", s);
    }

你可能感兴趣的:(Optional类)