java8 用Optional取代null

如何处理null

怎样作才能避免不期而至的NullPointerException呢?一般,能够在须要的地方添加null的检查(过于激进的防护式检查甚至会在不太须要的地方添加检测代码),而且添加的方式每每各有不一样。java

null-安全的第一种尝试:深层质疑

 “深层质疑”,缘由是它不断重复着一种模式:每次不肯定一个变量是否为null时,都须要添加一个进一步嵌套的if块,也增长了代码缩进的层数。很明显,这种方式不具有扩展性,同时还牺牲了代码的可读性。安全

 

null-安全的第二种尝试:过多的退出语句

 第二种尝试中,试图避免深层递归的if语句块,采用了一种不一样的策略:每次遭遇null变量,都返回一个字符串常量“Unknown”。然而,这种方案远非理想,如今这个方法有了四个大相径庭的退出点,使得代码的维护异常艰难。spa

 

使用Optional获取car的Insurance名称

汲取Haskell和Scala的灵感,Java 8中引入了一个新的类java.util.Optional<T>。这是一个封装Optional值的类。设计

public String getCarInsuranceName(Optional<Person> person){
    return person.flatMap(Person::getCar)
        .flatMap(Car::getInsurance)
        .map(Insurance::getName)
        .orElse("Unknown");//若是Optional的结果值为空,设置默认值
}

 

 

建立Optional对象

1. 声明一个空的Optional指针

能够经过静态工厂方法Optional.empty,建立一个空的Optional对象:code

Optional<Car> optCar = Optional.empty();

 

2. 依据一个非空值建立Optional对象

还可使用静态工厂方法Optional.of,依据一个非空值建立一个Optional对象:blog

若是car是一个null,这段代码会当即抛出一个NullPointerException,而不是等到试图访问car的属性值时才返回一个错误。递归

Optional<Car> optCar = Optional.of(car);

 

3. 可接受null的Optiona字符串

使用静态工厂方法Optional.ofNullable,能够建立一个容许null值的Optional对象:

若是car是null,那么获得的Optional对象就是个空对象。

Optional<Car> optCar = Optional.ofNullable(car);

 

Optional类的方法

 

 

 •null引用在历史上被引入到程序设计语言中,目的是为了表示变量值的缺失。   

•Java 8中引入了一个新的类java.util.Optional<T>,对存在或缺失的变量值进行建模。   

•可使用静态工厂方法Optional.empty、Optional.of以及Optional.ofNullable建立Optional对象。   

•Optional类支持多种方法,好比map、flatMap、filter,它们在概念上与Stream类中对应的方法十分类似。   

•使用Optional会迫使更积极地解引用Optional对象,以应对变量值缺失的问题,最终,能更有效地防止代码中出现不期而至的空指针异常。   

•使用Optional能帮助设计更好的API,用户只须要阅读方法签名,就能了解该方法是否接受一个Optional类型的值。

 

 

附:类代码

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;
    }
}

 

附:使用Optional从新定义Person/Car/Insurance的数据模型

public class Person {
    private Optional<Car> car;//人可能有车,也可能没有车,所以将这个字段声明为Optional

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

public class Car {
    private Optional<Insurance> insurance;//车可能进行了保险,也可能没有保险,因此将这个字段声明为Optional

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

public class Insurance {
    private String name;//保险公司必须有名字

    public String getName() {
        return name;
    }
}

 

文章来源:java8实战 第十章

相关文章
相关标签/搜索