国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java8中Optional的一些常見錯誤用法總結

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

2021-05-21 10:56Yanbin Java教程

我們知道 Java 8 增加了一些很有用的 API, 其中一個就是 Optional,下面這篇文章主要給大家介紹了關于Java8中Optional的一些常見錯誤用法的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下

前言

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 字段或方法參數時就變得復雜了,需要進行兩番檢查。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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(...) 方法時也有些累贅了

?
1
2
user.setmiddlename(optional.empty());
user.setmiddlename(optional.of("abc"));

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

?
1
2
3
4
5
6
7
8
9
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 檢查,總有一種不安全感,步步驚心,結果可能事與愿違。

?
1
2
3
4
5
6
7
public user getuserbyid(string userid) {
 if(userid != null) {
  return userdao.findbyid(userid);
 } else {
  return null;
 }
}

只是到了 java 8 改成了用 optional

?
1
2
3
return if(optional.ofnullable(userid)
 .map(id -> userdao.findbyid(id))
 .orelse(null);

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

?
1
2
userdao.findbyid(...)
getuserbyid(userid)

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

?
1
2
3
4
5
6
7
8
9
public user getuserbyid(string userid) { //拋出出 nullpointerexception 如果 null userid
 return userdao.findbyid(objects.requirenonull(userid, "invalid null userid");
}
 
//or
public user getuserbyid(string userid) { //拋出 illegalargumentexception 如果 null userid
 preconditions.checkargument(userid != null, "invalid null userid");
 return userdao.findbyid(userid);
}

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

?
1
2
3
4
5
6
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 對象

?
1
2
3
4
5
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(...) 的功能,只要看下它的源代碼就知道

?
1
2
3
4
5
6
7
8
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(...) 函數

?
1
2
3
4
5
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(...) 方法,例如

?
1
2
3
4
5
6
7
8
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(..) 兩個方法。看看它們的源代碼:

?
1
2
3
4
5
6
7
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 值的字面常量

?
1
2
optional.ofnullable(100); //這樣不好
optional.of(100);   //應該這么用

小結:

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

鏈接:

java 8 optional use cases

總結

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

原文鏈接:https://yanbin.blog/java8-optional-several-common-incorrect-usages/

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 欧美精品久久一区 | 国产成人网 | 久久精品国产免费 | 欧美大片免费影院在线观看 | 九九人人 | 亚洲在线一区 | 美女久久久 | 亚洲精品永久视频 | 欧美一区三区 | 国产女无套免费网站 | 国产大片一区 | 99这里只有精品 | 最新中文字幕 | 欧美精品一 | 国产精品久久久久久福利一牛影视 | 91精品久久久久久 | 国产精品视频网 | 国产精品a级| 久久精品免费观看 | 成人二区 | 久久夜色精品国产 | 久久com| 免费观看国产视频在线 | 成人综合区 | 国产一区色 | 99中文字幕| 91欧美激情一区二区三区成人 | 一级电影免费在线观看 | 在线视频 中文字幕 | 欧美一区二区三区在线观看视频 | 日韩av手机版 | 日韩在线| 91xxx在线观看| 国产精品久久久久aaaa | 黄色毛片网站在线观看 | 日韩综合网| 亚洲欧美在线观看 | 国产v日产∨综合v精品视频 | 久久精品国产一区二区三区不卡 | 免费在线a | 免费色网站 |