乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      使用Optional類來消除代碼中的null檢查

       泰榮林黑皮 2020-09-23
      作者丨一書生VOID

      lw900925.github.io/java/java8-optional.html

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

      避免使用null檢查

      作為Java開發(fā)人員,幾乎所有人都遇到過NullPointerException異常,大多數(shù)人遇到NullPointerException異常時(shí)都會在異常出現(xiàn)的地方加上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);
                  }
              }
          }
      }

      這是比較普遍的做法,為了避免出現(xiàn)NullPointerException異常,手動對可能為null值進(jìn)行了處理,不過代碼看起來非常糟糕,業(yè)務(wù)邏輯被淹沒在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語句嵌套,但本質(zhì)上是一樣的,方法內(nèi)有三個(gè)不同的返回點(diǎn),出錯后調(diào)試也不容易,因?yàn)槟悴恢朗悄莻€(gè)值導(dǎo)致了NullPointerException異常。

      基于上面的原因,Java 8中引入了一個(gè)新的類Optional,用以避免使用null值引發(fā)的種種問題。擴(kuò)展:如何更優(yōu)雅的處理空值?

      Optional類

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

      創(chuàng)建Optional對象

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

      empty()方法用于創(chuàng)建一個(gè)沒有值的Optional對象:

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

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

      of()方法使用一個(gè)非空的值創(chuàng)建Optional對象:

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

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

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

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

      提取Optional對象中的值

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

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

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

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

      使用orElse()方法獲取值

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

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

      下面來看看這三個(gè)方法的具體用法:

      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類還提供了一個(gè)ifPresent()方法,該方法接收一個(gè)Consumer<? super T>函數(shù)式接口,一般用于將信息打印到控制臺:

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

      使用filter()方法過濾

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

      Optional<String> optional = Optional.of('lw900925@163.com');
      optional = optional.filter(str -> str.contains('164'));

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

      如何正確使用Optional

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

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

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

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

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

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

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

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

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

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

      正確創(chuàng)建Optional對象

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

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

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

      orElse()方法的使用

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

      上面的代碼表示判斷字符串str是否為空,不為空就返回,否則,返回一個(gè)常量。使用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);

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

        本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多