日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

Optional類是JAVA 8新增的一個類,用以解決程序中常見的NullPointerException異常問題。本篇文章將詳細介紹Optional類,以及如何用它消除代碼中的null檢查。

如何正確的使用Java8中的Optional類來消除代碼中的null檢查

 

避免使用null檢查

作為Java開發人員,幾乎所有人都遇到過NullPointerException異常,大多數人遇到NullPointerException異常時都會在異常出現的地方加上if代碼塊來判斷值不為空,比如下面的代碼:

public void bindUserToRole(User user) {
    if (user != null) {
        String roleId = user.getRoleId();
        if (roleId != null) {
            Role role = roleDao.findOne(roleId);
            if (role != null) {
                role.setUserId(user.getUserId());
                roleDao.save(role);
            }
        }
    }
}

這是比較普遍的做法,為了避免出現NullPointerException異常,手動對可能為null值進行了處理,不過代碼看起來非常糟糕,業務邏輯被淹沒在if邏輯判斷中,也許下面的代碼看起來可讀性稍好一些:

public String bindUserToRole(User user) {
    if (user == null) {
        return;
    }

    String roleId = user.getRoleId();
    if (roleId == null) {
        return;
    }

    Role = roleDao.findOne(roleId);
    if (role != null) {
        role.setUserId(user.getUserId());
        roleDao.save(role);
    }
}

上面的代碼避免了深層的if語句嵌套,但本質上是一樣的,方法內有三個不同的返回點,出錯后調試也不容易,因為你不知道是那個值導致了NullPointerException異常。

基于上面的原因,Java 8中引入了一個新的類Optional,用以避免使用null值引發的種種問題。擴展:如何更優雅的處理空值?

Optional類

java.util.Optional<T>類是一個封裝了Optional值的容器對象,Optional值可以為null,如果值存在,調用isPresent()方法返回true,調用get()方法可以獲取值。

創建Optional對象

Optional類提供類三個方法用于實例化一個Optional對象,它們分別為empty()、of()、ofNullable(),這三個方法都是靜態方法,可以直接調用。

empty()方法用于創建一個沒有值的Optional對象:

Optional<String> emptyOpt = Optional.empty();

empty()方法創建的對象沒有值,如果對emptyOpt變量調用isPresent()方法會返回false,調用get()方法拋出NullPointerException異常。

of()方法使用一個非空的值創建Optional對象:

String str = "Hello World";
Optional<String> notNullOpt = Optional.of(str);

ofNullable()方法接收一個可以為null的值:

Optional<String> nullableOpt = Optional.ofNullable(str);

如果str的值為null,得到的nullableOpt是一個沒有值的Optional對象。

提取Optional對象中的值

如果我們要獲取User對象中的roleId屬性值,常見的方式是直接獲取:

String roleId = null;
if (user != null) {
    roleId = user.getRoleId();
}

使用Optional中提供的map()方法可以以更簡單的方式實現:

Optional<User> userOpt = Optional.ofNullable(user);
Optional<String> roleIdOpt = userOpt.map(User::getRoleId);

使用orElse()方法獲取值

Optional類還包含其他方法用于獲取值,這些方法分別為:

  • orElse():如果有值就返回,否則返回一個給定的值作為默認值;
  • orElseGet():與orElse()方法作用類似,區別在于生成默認值的方式不同。該方法接受一個Supplier<? extends T>函數式接口參數,用于生成默認值;
  • orElseThrow():與前面介紹的get()方法類似,當值為null時調用這兩個方法都會拋出NullPointerException異常,區別在于該方法可以指定拋出的異常類型。

下面來看看這三個方法的具體用法:

String str = "Hello World";
Optional<String> strOpt = Optional.of(str);
String orElseResult = strOpt.orElse("Hello Shanghai");
String orElseGet = strOpt.orElseGet(() -> "Hello Shanghai");
String orElseThrow = strOpt.orElseThrow(
        () -> new IllegalArgumentException("Argument 'str' cannot be null or blank."));

此外,Optional類還提供了一個ifPresent()方法,該方法接收一個Consumer<? super T>函數式接口,一般用于將信息打印到控制臺:

Optional<String> strOpt = Optional.of("Hello World");
strOpt.ifPresent(System.out::println);

使用filter()方法過濾

filter()方法可用于判斷Optional對象是否滿足給定條件,一般用于條件過濾:

Optional<String> optional = Optional.of("[email protected]");
optional = optional.filter(str -> str.contains("164"));

在上面的代碼中,如果filter()方法中的Lambda表達式成立,filter()方法會返回當前Optional對象值,否則,返回一個值為空的Optional對象。Java知音公眾號內回復“后端面試”,送你一份Java面試題寶典。

如何正確使用Optional

通過上面的例子可以看出,Optional類可以優雅的避免NullPointerException帶來的各種問題,不過,你是否真正掌握了Optional的用法?

假設你試圖使用Optional來避免可能出現的NullPointerException異常,編寫了如下代碼:

Optional<User> userOpt = Optional.ofNullable(user);
if (userOpt.isPresent()) {
    User user = userOpt.get();
    // do something...
} else {
    // do something...
}

坦白說,上面的代碼與我們之前的使用if語句判斷空值沒有任何區別,沒有起到Optional的正真作用:

if (user != null) {
    // do something...
} else {
    // do something...
}

當我們從之前版本切換到Java 8的時候,不應該還按照之前的思維方式處理null值,Java 8提倡函數式編程,新增的許多API都可以用函數式編程表示,Optional類也是其中之一。這里有幾條關于Optional使用的建議:

  • 盡量避免在程序中直接調用Optional對象的get()和isPresent()方法;
  • 避免使用Optional類型聲明實體類的屬性;

第一條建議中直接調用get()方法是很危險的做法,如果Optional的值為空,那么毫無疑問會拋出NullPointerException異常,而為了調用get()方法而使用isPresent()方法作為空值檢查,這種做法與傳統的用if語句塊做空值檢查沒有任何區別。

第二條建議避免使用Optional作為實體類的屬性,它在設計的時候就沒有考慮過用來作為類的屬性,如果你查看Optional的源代碼,你會發現它沒有實現java.io.Serializable接口,這在某些情況下是很重要的(比如你的項目中使用了某些序列化框架),使用了Optional作為實體類的屬性,意味著他們不能被序列化。

下面我們通過一些例子講解Optional的正確用法:

正確創建Optional對象

上面提到創建Optional對象有三個方法,empty()方法比較簡單,沒什么特別要說明的。主要是of()和ofNullable()方法。當你很確定一個對象不可能為null的時候,應該使用of()方法,否則,盡可能使用ofNullable()方法,比如:

public static void method(Role role) {
    // 當Optional的值通過常量獲得或者通過關鍵字new初始化,可以直接使用of()方法
    Optional<String> strOpt = Optional.of("Hello World");
    Optional<User> userOpt = Optional.of(new User());

    // 方法參數中role值不確定是否為null,使用ofNullable()方法創建
    Optional<Role> roleOpt = Optional.ofNullable(role);
}

orElse()方法的使用

return str != null ? str : "Hello World"

上面的代碼表示判斷字符串str是否為空,不為空就返回,否則,返回一個常量。使用Optional類可以表示為:

return strOpt.orElse("Hello World")

簡化if-else

User user = ...
if (user != null) {
    String userName = user.getUserName();
    if (userName != null) {
        return userName.toUpperCase();
    } else {
        return null;
    }
} else {
    return null;
}

上面的代碼可以簡化成:

User user = ...
Optional<User> userOpt = Optional.ofNullable(user);

return userOpt.map(User::getUserName)
            .map(String::toUpperCase)
            .orElse(null);

總結一下,新的Optional類讓我們可以以函數式編程的方式處理null值,拋棄了Java 8之前需要嵌套大量if-else代碼塊,使代碼可讀性有了很大的提高。

分享到:
標簽:Java8 Optional
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定