java8 用Optional取代null


如何處理null

怎樣做才能避免不期而至的NullPointerException呢?通常,可以在需要的地方添加null的檢查(過於激進的防御式檢查甚至會在不太需要的地方添加檢測代碼),並且添加的方式往往各有不同。

null-安全的第一種嘗試:深層質疑

 “深層質疑”,原因是它不斷重復着一種模式:每次不確定一個變量是否為null時,都需要添加一個進一步嵌套的if塊,也增加了代碼縮進的層數。很明顯,這種方式不具備擴展性,同時還犧牲了代碼的可讀性。

 

null-安全的第二種嘗試:過多的退出語句

 第二種嘗試中,試圖避免深層遞歸的if語句塊,采用了一種不同的策略:每次遭遇null變量,都返回一個字符串常量“Unknown”。然而,這種方案遠非理想,現在這個方法有了四個截然不同的退出點,使得代碼的維護異常艱難。

 

使用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對象:

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

 

2. 依據一個非空值創建Optional

還可以使用靜態工廠方法Optional.of,依據一個非空值創建一個Optional對象:

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM