javaJava8

用Optional取代null

2018-06-02  本文已影响94人  小鱼嘻嘻
null引发的问题以及为什么要避免null引用

先看一个例子

public static void main(String[] args) {
        new Person().getCar().getInsurance().getName();
    }

    static class Person {
        private Car car;

        public Car getCar() {
            return car;
        }

        public void setCar(Car car) {
            this.car = car;
        }
    }

    static class Car {
        private Insurance insurance;

        public Insurance getInsurance() {
            return insurance;
        }

        public void setInsurance(Insurance insurance) {
            this.insurance = insurance;
        }
    }

    static class Insurance {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

意思也就是说获取一个人的车的保险公司的名称。可以看到的是,并不是每一个都有车,也并不是每一个车都有保险。这样的获取是会发生NullpointException,如何避免呢?Java8之前我们可能采用防御式编程。

    Person p = new Person();
        if (p != null) {
            Car car = p.getCar();
            if (car != null) {
                Insurance insurance = car.getInsurance();
                if (insurance != null) {
                    System.out.println(insurance.getName());
                }
            }
        }

这样的代码会看着结构不清晰,可读性很差。如何解决呢?请看Java8引入的Optional。

Optional 类
static class Person {
        private Optional<Car> car;

        public Optional<Car> getCar() {
            return car;
        }

        public void setCar(Optional<Car> car) {
            this.car = car;
        }
    }

    static class Car {
        private Optional<Insurance> insurance;

        public Optional<Insurance> getInsurance() {
            return insurance;
        }

        public void setInsurance(Optional<Insurance> insurance) {
            this.insurance = insurance;
        }
    }

    static class Insurance {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
       Optional<Insurance> insurance = Optional.of(new Insurance());
        Optional<String> s = insurance.map(Insurance::getName);

这种map的转换和之前的stream基本一样,只是这个是单个元素的转换而已。

 String s1 = person.
            flatMap(Person::getCar).
            flatMap(Car::getInsurance).
            map(Insurance::getName).
            orElse("unknown");

对比我们的第一份代码这个代码结构就太清晰了,层次和逻辑也很清新。

默认行为以及解引用Optional对象
两个Optional对象组合

假设你试图获取保险最便宜的。

private static Optional<Insurance> getCheapestInsurance(Optional<Person> person, Optional<Car> car) {
        if (person.isPresent() && car.isPresent()) {
            return getCheapestInsurance(person.get(), car.get());
        }
        return Optional.empty();
    }

    private static Optional<Insurance> getCheapestInsurance(Person person, Car Car) {
        return null;
    }

这种并不是最优的解决方法,请看下面:

return person.flatMap(p -> car.map(c -> getCheapestInsurance(p, c))).orElse(Optional.empty());
使用filter剔除特定的值
 insurance.filter(insurance1 -> insurance1.getName().equals("AAA"))
            .ifPresent(x -> System.out.println(x));

这个filter和stream的filter也是一样的。

方法 描述
empty 返回一个空的Optional实例
filter 如果值存在并且满足提供的谓词,就返回Optional对象,否则返回空
flatMap 如果值存在,就对该值执行mapping函数调用,返回一个Optional对象,否则就返回一个空Optional
get 如果值存在就返回Optional对象,否则报异常
ifPresent 如果值存在就执行该方法,不存在什么也不做
isPresent 存在就返回true,不存在就返回false
map 如果值存在就执行mapping函数调用
of 将制定值用Optional封装之后返回,如果为空就返回一个Optional空对象
orElse 如果有值就返回值,没有就返回一个默认值
orElseGet 如果有值就返回,没有值就执行supplier函数
orElseThrow 如果有值就返回,否则抛出指定的异常
上一篇下一篇

猜你喜欢

热点阅读