亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

Java8中Optional的一些常見錯誤用法總結

2024-07-14 08:41:51
字體:
來源:轉載
供稿:網友

前言

Java 8 引入的 Optional 類型,基本是把它當作 null 值優雅的處理方式。其實也不完全如此,Optional 在語義上更能體現有還是沒有值。所以它不是設計來作為 null 的替代品,如果方法返回 null 值表達了二義性,沒有結果或是執行中出現異常。

在 Oracle  做  Java 語言工作的  Brian Goetz 在 Stack Overflow 回復 Should Java 8 getters return optional type? 中講述了引入  Optional 的主要動機。

Our intention was to provide a limited mechanism for library method return types where there needed to be a clear way to represent “no result”, and using null for such was overwhelmingly likely to cause errors.

說的是  Optional 提供了一個有限的機制讓類庫方法返回值清晰的表達有與沒有值,避免很多時候 null 造成的錯誤。并非有了  Optional 就要完全杜絕 NullPointerException。

在 Java 8 之前一個實踐是方法返回集合或數組時,應返回空集合或數組表示沒有元素; 而對于返回對象,只能用 null 來表示不存在,現在可以用  Optional 來表示這個意義。

自 Java8 于  2014-03-18 發布后已 5 年有余,這里就列舉幾個我們在項目實踐中使用 Optional 常見的幾個用法。

Optional 類型作為字段或方法參數

這兒把 Optional  類型用為字段(類或實例變量)和方法參數放在一起來講,是因為假如我們使用 IntelliJ IDEA 來寫 Java 8 代碼,IDEA 對于  Optional 作為字段和方法參數會給出同樣的代碼建議:

Reports any uses of java.util.Optional<T> , java.util.OptionalDouble , java.util.OptionalInt , java.util.OptionalLong or com.google.common.base.Optional as the type for a field or parameter. Optional was designed to provide a limited mechanism for library method return types where there needed to be a clear way to represent "no result". Using a field with type java.util.Optional is also problematic if the class needs to be Serializable , which java.util.Optional is not.

不建議用任何的 Optional 類型作為字段或參數,Optional 設計為有限的機制讓類庫方法返回值清晰的表達 "沒有值"。 Optional 是不可被序列化的,如果類是可序列化的就會出問題。

上面其實重復了 Java 8 引入  Optional 的意圖,我們還有必要繼續深入理解一下為什么不該用  Optional 作為字段或方法參數。

當我們選擇 Optional 類型而非內部包裝的類型后,應該是假定了該 Optional 類型不為 null,否則我們在使用 Optional 字段或方法參數時就變得復雜了,需要進行兩番檢查。

public class User { private String firstName; private Optional<String> middleName = Optional.empty(); private String lastName;  public void setMiddleName(Optional<String> middleName) {  this.middleName = middleName; }  public String getFullName() {  String fullName = firstName;  if(middleName != null) {   if(middleName.isPresent()){    fullName = fullName.concat("." + middleName.get());  }   return fullName.concat("." + lastName); }}

由于 middleName 的 setter 方法,我們可能造成 middleName 變為 null 值,所以在構建 fullName 時必須兩重檢查。

并且在調用 setMiddleName(...) 方法時也有些累贅了

user.setMiddleName(Optional.empty());user.setMiddleName(Optional.of("abc"));

而如果字段類型非 Optional 類型,而傳入的方法參數為 Optional 類型,要進行賦值的話

 private String middleName;  public void updateMiddleName(Optional<String> middleName) {  if(middleName != null) {   this.middleName = middleName.orElse(null);  } else {   this.middleName = null;  } }

前面兩段代碼如果應用 Optional.ofNullable(...) 包裹 Optional 來替代 if(middleName != null) 就更復雜了。

對于本例直接用 String 類型的 middleName  作為字段或方法參數就行,null 值可以表達沒有 middleName。如果不允許 null 值  middleName, 顯式的進行入口參數檢查而拒絕該輸入 -- 拋出異常。

利用 Optional 過度檢查方法參數

這一 Optional 的用法與之前的可能為 null 值的方法參數,不分清紅皂白就用 if...else 檢查,總有一種不安全感,步步驚心,結果可能事與愿違。

public User getUserById(String userId) { if(userId != null) {  return userDao.findById(userId); } else {  return null; }}

只是到了 Java 8 改成了用 Optional

 return if(Optional.ofNullable(userId)  .map(id -> userDao.findById(id))  .orElse(null);

上面兩段代碼其實是同樣的問題,如果輸入的 userId 是 null 值不調用 findById(...) 方法而直接返回 null 值,這就有兩個問題

userDao.findById(...)getUserById(userId)

這種情況下立即拋出 NullPointerException 是一個更好的主意,參考下面的代碼

public User getUserById(String userId) { //拋出出 NullPointerException 如果 null userId return userDao.findById(Objects.requireNoNull(userId, "Invalid null userId");} //orpublic User getUserById(String userId) { //拋出 IllegalArgumentException 如果 null userId Preconditions.checkArgument(userId != null, "Invalid null userId"); return userDao.findById(userId);}

即使用了 Optional 的 orElseThrow 拋出異常也不能明確異常造成的原因,比如下面的代碼

public User getUserById(String userId) { return Optional.ofNullable(userId)  .map(id -> userDao.findById(id))  orElseThrow(() ->    new RuntimeException("userId 是 null 或 findById(id) 返回了 null 值"));}

糾正辦法是認真的審視方法的輸入參數,對不符合要求的輸入應立即拒絕,防止對下層的壓力與污染,并報告出準確的錯誤信息,以有利于快速定位修復。

Optional.map(...) 中再次 null 值判斷

假如有這樣的對象導航關系 user.getOrder().getProduct().getId() , 輸入是一個  user 對象

 String productId = Optional.ofNullable(user)  .map(User::getOrder)  .flatMap(order -> Optional.ofNullable(order.getProduct())) //1  .flatMap(product -> Optional.ofNullable(product.getId())) //2  .orElse("");

#1 和 #2 中應用 flatMap 再次用 Optional.ofNullable() 是因為擔心 order.getProduct() 或 product.getId() 返回了 null 值,所以又用 Optional.ofNullable(...) 包裹了一次。代碼的執行結果仍然是對的,代碼真要這么寫的話真是 Oracle 的責任。這忽略了 Optional.map(...) 的功能,只要看下它的源代碼就知道

 public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {  Objects.requireNonNull(mapper);  if (!isPresent())   return empty();  else {   return Optional.ofNullable(mapper.apply(value));  } }

map(...) 函數中已有考慮拆解后的 null 值,因此呢 flatMap 中又 Optional.ofNullable 是多余的,只需簡單一路用 map(...) 函數

 String productId = Optional.ofNullable(user)  .map(User::getOrder)  .map(order -> order.getProduct()) //1  .map(product -> product.getId()) //2  .orElse("");

Optional.ofNullable 應用于明確的非  null 值

如果有時候只需要對一個明確不為 null 的值進行 Optional 包裝的話,就沒有必要用 ofNullable(...) 方法,例如

public Optional<User> getUserById(String userId) { if("ADMIN".equals(userId)) {  User adminUser = new User("admin");  return Optional.ofNullable(adminUser); //1 } else {  return userDao.findById(userId); }}

在代碼 #1 處非常明確 adminUser 是不可能為 null 值的,所以應該直接用 Optional.of(adminUser) 。這也是為什么 Optional 要聲明 of(..) 和 ofNullable(..) 兩個方法??纯此鼈兊脑创a:

 public static <T> Optional<T> of(T value) {  return new Optional<>(value); }  public static <T> Optional<T> ofNullable(T value) {  return value == null ? empty() : of(value); }

知道被包裹的值不可能為 null 時調用 ofNullable(value) 多了一次多余的 null 值檢查。相應的對于非 null 值的字面常量

Optional.ofNullable(100); //這樣不好Optional.of(100);   //應該這么用

小結:

  1. 要理解 Optional 的設計用意,所以語意上應用它來表達有/無結果,不適于作為類字段與方法參數
  2. 傾向于方法返回單個對象,用 Optional 類型表示無結果以避免 null 值的二義性
  3. Optional 進行方法參數檢查不能掩蓋了錯誤,最好是明確非法的參數輸入及時拋出輸入異常
  4. 對于最后兩種不正確的用法應熟悉 Optional 的源代碼實現就能規避

鏈接:

Java 8 Optional use cases

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩在线视频导航| 欧美一级淫片丝袜脚交| 久久成人人人人精品欧| 色伦专区97中文字幕| 成人两性免费视频| 亚洲欧美制服丝袜| 亚洲视频自拍偷拍| 日韩精品免费在线| 亚洲欧美成人在线| 欧美日韩一区二区免费视频| 欧美最猛性xxxxx亚洲精品| 国内精品久久久久久中文字幕| 日韩欧美在线中文字幕| 日韩大片免费观看视频播放| 久久精品99久久久久久久久| 最新日韩中文字幕| 91精品国产自产91精品| 亚洲欧美日韩中文在线制服| 色伦专区97中文字幕| 精品欧美激情精品一区| 日韩欧美国产激情| 91精品国产色综合久久不卡98| 亚洲一区999| 欧美视频在线视频| 91美女高潮出水| 国产成人精品一区二区| 琪琪第一精品导航| 欧美三级欧美成人高清www| 日韩一区av在线| 久久久久久久久久久成人| 亚洲电影免费观看高清完整版在线观看| 最新91在线视频| 欧美极品少妇与黑人| 青草青草久热精品视频在线网站| 国产成人精品综合| 欧美中文字幕在线播放| 亚洲欧美成人一区二区在线电影| 日韩在线免费高清视频| 日韩在线观看免费高清| 国产精品久久久久7777婷婷| 亚洲视频精品在线| 清纯唯美亚洲综合| 久热在线中文字幕色999舞| 亚洲天堂免费观看| 久久亚洲成人精品| 国产成人a亚洲精品| 91欧美视频网站| 韩国三级电影久久久久久| 日韩免费视频在线观看| 欧美日韩中文字幕日韩欧美| 国内精品小视频| 色天天综合狠狠色| 动漫精品一区二区| 亚洲精品有码在线| 一区二区三区高清国产| 亚洲午夜av久久乱码| 国产精品福利无圣光在线一区| 亚洲精品成a人在线观看| 国产啪精品视频| 国产一区二区在线免费视频| 亚洲爱爱爱爱爱| 欧美高清自拍一区| 精品在线观看国产| 亚洲最新av在线网站| 欧美理论在线观看| 日韩在线观看你懂的| 亚洲精品av在线| 国产欧美欧洲在线观看| 日韩精品一区二区三区第95| 亚洲第一级黄色片| 亚洲深夜福利在线| 中文字幕综合在线| 欧美激情伊人电影| 欧美日韩国产综合新一区| 欧美激情日韩图片| 精品国产乱码久久久久久虫虫漫画| 中文字幕亚洲综合久久| 欧美日本在线视频中文字字幕| 欧美综合一区第一页| 黄色成人av在线| 岛国av在线不卡| 亚洲第一男人av| 亚洲天堂第二页| 亚洲最大福利视频网| 热99久久精品| 日韩精品极品毛片系列视频| 欧美视频第一页| 国产精品入口免费视| 国产精品久在线观看| 国产精品久久久久久久久久免费| 欧美亚洲激情在线| 亚洲一级一级97网| 日韩女优在线播放| 国语自产精品视频在线看一大j8| 久久久噜噜噜久噜久久| 久久久久久噜噜噜久久久精品| 欧美最近摘花xxxx摘花| 欧美天堂在线观看| 国产精品视频成人| 狠狠色狠色综合曰曰| 欧美一级视频一区二区| 久久久久久免费精品| 午夜精品蜜臀一区二区三区免费| 国产精品网址在线| 亚洲一区二区三| 少妇久久久久久| 国产一区二区三区在线免费观看| 国产精品一区二区久久精品| 自拍偷拍亚洲一区| 成人黄色在线免费| 欧美在线视频免费| y97精品国产97久久久久久| 97免费视频在线| 亚洲人成伊人成综合网久久久| 欧美日韩一区二区在线| 亚洲free性xxxx护士hd| 日韩av在线网页| 91在线视频导航| 亚洲视频在线看| 97超级碰在线看视频免费在线看| 欧美激情va永久在线播放| 亚洲国产精品久久91精品| 日韩毛片在线观看| 精品亚洲精品福利线在观看| 成人中文字幕在线观看| 欧美性高潮床叫视频| 国产精品自产拍在线观看| 成人激情视频免费在线| 日韩欧美在线视频日韩欧美在线视频| 91久久久久久国产精品| 久久97精品久久久久久久不卡| 国产91在线播放九色快色| 欧美一区二区.| 国外日韩电影在线观看| 69久久夜色精品国产69| 国产精品1234| 欧美贵妇videos办公室| 日韩精品视频中文在线观看| 成人免费在线视频网站| 日本欧美黄网站| 精品高清一区二区三区| 日本欧美黄网站| 亚洲电影免费观看高清完整版| 最近2019免费中文字幕视频三| 少妇高潮久久久久久潘金莲| 久久亚洲精品中文字幕冲田杏梨| 日本三级久久久| 亚洲国产欧美一区二区三区久久| 亚洲综合色av| 国产精品视频资源| 欧美黑人视频一区| 亚洲一区二区福利| 国产精品网站视频| 日韩成人在线视频观看| 狠狠干狠狠久久| 国语自产精品视频在线看一大j8| 亚洲人成电影网站色xx| 日韩av一区二区在线观看| 性亚洲最疯狂xxxx高清| 福利微拍一区二区| 国产精品国产三级国产专播精品人| 日韩精品久久久久久福利| 亚洲成年网站在线观看| 日韩av中文字幕在线|