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實戰 第十章

相關文章
相關標籤/搜索