精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

這么簡單的三目運算符竟然也有這么多坑?

開發 前端
最近,阿粉在一個業務改造中,使用三目運算符重構了業務代碼,沒想到測試的時候竟然發生 NPE 的問題。

[[328294]]

最近,阿粉在一個業務改造中,使用三目運算符重構了業務代碼,沒想到測試的時候竟然發生 NPE 的問題。

[[328295]]

重構代碼非常簡單,代碼如下:

  1. // 方法返回參數類型為 Integer 
  2. //  private Integer code; 
  3. SimpleObj simpleObj = new SimpleObj(); 
  4. // 其他業務邏輯 
  5. if (simpleObj == null) { 
  6.     return -1; 
  7. else { 
  8.     return simpleObj.getCode(); 

這段 if 判斷,阿粉看到的時候,感覺很是繁瑣,于是使用三目運算符重構了一把,代碼如下:

  1. // 方法返回參數類型為 Integer 
  2. SimpleObj simpleObj = new SimpleObj(); 
  3. // 其他業務邏輯 
  4. return simpleObj == null ? -1 : simpleObj.getCode(); 

測試的時候,第四行代碼拋出了空指針,這里代碼很簡單,顯然只有 simpleObj#getCode才有可能發生 NPE 問題。

但是我明明為 simpleObj做過判空判斷,simpleObj 對象肯定不是 null,那么只有 simpleObj#getCode 返回為 null。但是我的代碼并沒有對這個方法返回值做任何操作,為何會觸發 NPE?

難道是又是自動拆箱導致的 NPE 問題?

在解答這個問題之前,我們首先復習一下三目運算符。

三目運算符

三目運算符,官方英文名稱:Conditional Operator ? :,中文直譯條件表達式,本文不糾結名稱,統一使用三目運算符。

三目運算符的基本用法非常簡單,它由三個操作數的運算符構成,形式為:

  1. <表達式 1><表達式 2>:<表達式 3> 

三目運算符的計算從左往右計算,首先需要計算計算表達式 1 ,其結果類型必須為 Boolean 或 boolean,否則發生編譯錯誤。

當表達式 1 的結果為 true,將會執行表達式 2,否則將會執行表達式 3。

表達式 2 與表達式 3 最后的類型必須得有返回結果,即不能為是 void,若為 void ,編譯時將會報錯。

最后需要注意的是,表達式 2 與表達式 3 不會被同時執行,兩者只有一個會被執行。

踩坑案例

了解完三目運算符的基本原理,我們簡化一下開頭例子,復現一下三目運算符使用過程的一些坑。假設我們的例子簡化成如下:

  1. boolean flag = true; //設置成true,保證表達式 2 被執行 
  2. int simpleInt = 66; 
  3. Integer nullInteger = null

案例 1

第一個案例我們根據如下計算 result 的值。

  1. int result = flag ? nullInteger : simpleInt; 

這個案例為開頭的例子的簡化版本,運算上述代碼,將會發生 NPE 的。

為什么會發發生 NPE 呢?

這里可以給大家一個小技巧,當我們從代碼上沒辦法找到答案時,我們可以試試查看一下編譯之后字節碼,或許是 Java 編譯之后增加某些東西,從而導致問題。

使用 javap -s -c class 查看 class 文件字節碼,如下:

可以看到字節碼中加入一個拆箱操作,而這個拆箱只有可能發生在 nullInteger。

那么為什么 Java 編譯器在編譯時會對表達式進行拆箱?難道所有數字類型的包裝類型都會進行拆箱嗎?

三目運算符表達式發生自動拆箱,其實官方在 「The Java Language Specification(簡稱:JLS)」15.25 節[1]中做出一些規定,部分內容如下:

  • JDK7 規范
  • If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression.
  • If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.

用大白話講,如果表達式 2 與表達式 3 類型相同,那么這個不用任何轉換,三目運算符表達式結果當然與表達式 2,3 類型一致。

當表達 2 或表達式 3 其中任一一個是基本數據類型,比如 int,而另一個表達式類型為包裝類型,比如 Integer,那么三目運算符表達式結果類型將會為基本數據類型,即 int。

  • ps:有沒有疑問?為什么不規定最后結果類型都為包裝類那?

這是 Java 語言層面一種規范,但是這個規范如果強制讓程序員執行,想必平常使用三目運算符將會比較麻煩。所以面對這種情況, Java 在編譯器在編譯過程加入自動拆箱進制。

所以上述代碼可以等同于下述代碼:

  1. int result = flag ? nullInteger.intValue() : simpleInt; 

如果我們一開始的代碼如上所示,那么這里錯誤點其實就很明顯了。

案例 2

接下來我們在第一個案例基礎上修改一下:

  1. boolean flag = true; //設置成true,保證表達式 2 被執行 
  2. int simpleInt = 66; 
  3. Integer nullInteger = null
  4. Integer objInteger = Integer.valueOf(88); 
  5.  
  6. int result = flag ? nullInteger : objInteger; 

運行上述代碼,依然會發生 NPE 的問題。當然這次問題發生點與上一個案例不一樣,但是錯誤原因卻是一樣,還是因為自動拆箱機制導致。

這一次表達式 2 與表達式 3 都為包裝類 Integer,所以三目運算符的最后結果類型也會是 Integer。

但是由于 result是 int 基本數據類型,好家伙,數據類型不一致,編譯器將會對三目運算符的結果進行自動拆箱。由于結果為 null,自動拆箱將報錯了。

上述代碼等同為:

  1. int result = (flag ? nullInteger : objInteger).intValue(); 

案例 3

我們再稍微改造一下案例 1 的例子,如下所示:

  1. boolean flag = true; //設置成true,保證表達式 2 被執行 
  2. int simpleInt = 66; 
  3. Integer nullInteger = null
  4. Integer result = flag ? nullInteger : simpleInt; 

案例 3 與案例 1 右邊部分完全相同,只不過左邊部分的類型不一樣,一個為基本數據類型 int,一個為 Integer。

按照案例 1 的分析,這個也會發生 NPE 問題,原因與案例 1 一樣。

這個之所以拿出來,其實想說下,上述三目運算符的結果為 int 類型,而左邊類型為 Integer,所以這里將會發生自動裝箱操作,將 int類型轉化為 Integer。

上述代碼等同為:

  1. Integer result = Integer.valueOf(flag ? nullInteger.intValue() : simpleInt); 

案例 4

最后一個案例,與上面案例都不一樣,代碼如下:

  1. boolean flag = true; //設置成true,保證表達式 2 被執行 
  2. Integer nullInteger = null
  3. Long objLong = Long.valueOf(88l); 
  4.  
  5. Object result = flag ? nullInteger : objLong; 

運行上述代碼,依然將會發生 NPE 的問題。

這個案例表達式 2 與表達式 3 類型不一樣,一個為 Integer,一個為 Long,但是這兩個類型都是 Number的子類。

面對上述情況,JLS 規定:

  • Otherwise, binary numeric promotion (§5.6.2[2]) is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands.
  • Note that binary numeric promotion performs value set conversion (§5.1.13[3]) and may perform unboxing conversion (§5.1.8[4]).

大白話講,當表達式 2 與表達式 3 類型不一致,但是都為數字類型時,低范圍類型將會自動轉為高范圍數據類型,即向上轉型。這個過程將會發生自動拆箱。

  • Java 中向上轉型并不需要添加任何轉化,但是向下轉換必須強制添加類型轉換。

上述代碼轉化比較麻煩,我們先從字節碼上來看:

第一步,將 nullInteger拆箱。

第二步,將上一步的值轉為 long 類型,即 (long)nullInteger.intValue()。

第三步,由于表達式 2 變成了基本數據類型,表達式 3 為包裝類型,根據案例 1 講到的規則,包裝類型需要轉為基本數據類型,所以表達式 3 發生了拆箱。

第四步,由于三目運算符最后的結果類型為基本數據類型:long,但是左邊類型為 Object,這里就需要把 long 類型裝箱轉為包裝類型。

所以最后代碼等同于:

  1. Object result = Long.valueOf(flag ? (long)nullInteger.intValue() : objLong.longValue()); 

總結

看完上述四個案例,想必大家應該會有種感受,沒想到這么簡單的三目運算符,既然暗藏這么多「殺機」。

不過大家也不用過度害怕,不使用三目運算符。只要我們在開發過程重點注意包裝類型的自動拆箱問題就好了,另外也要注意三目運算符的計算結果再賦值的時候自動拆箱引發的 NPE 的問題。

最好大家在開發過程中,都遵守一定的規范,即保持表達式 2 與表達式 3 的類型一致,不讓 Java 編譯器有自動拆箱的機會。

建議大家沒事經常看下阿里出品的『Java 開發手冊』,在最新的「泰山版」就增加三目運算符的這一節規范。

ps:公號消息回復:『開發手冊』,獲取最新版的 Java 開發手冊。

最后一定要做好的單元測試,不要慣性思維,覺得這么簡單的一個東西,看起來根本不可能出錯的。

參考資料

[1]15.25 節: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.25

[2]§5.6.2: https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2

[3]§5.1.13: https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.13

[4]§5.1.8: https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.8

[5]Java 開發手冊》解讀:三目運算符為何會導致 NPE?: https://developer.aliyun.com/article/758784

 

責任編輯:武曉燕 來源: Java極客技術
相關推薦

2022-07-06 11:47:27

JAVAfor循環

2018-06-26 15:00:24

Docker安全風險

2024-04-02 08:41:10

ArrayListSubList場景

2021-02-03 20:19:08

Istio流量網格

2025-07-23 10:13:57

2017-12-21 19:38:50

潤乾中間表

2021-01-14 05:08:44

編譯鏈接

2022-07-26 23:43:29

編程語言開發Java

2013-01-15 09:41:45

編程語言

2024-02-20 08:09:51

Java 8DateUtilsDate工具類

2023-11-13 08:49:54

2017-07-04 14:01:40

機房機柜

2017-07-12 08:20:32

閃存用途企業

2021-06-10 09:00:33

單例模式數據庫

2022-03-03 07:00:43

Mybatiswhere標簽

2018-12-11 12:58:20

CPU散熱器鰭片

2019-08-27 08:17:57

云計算安全云服務商

2017-06-16 16:16:36

庫存扣減查詢

2018-05-29 14:57:59

HashMap容量初始化

2025-05-26 09:30:00

SQL數據庫索引
點贊
收藏

51CTO技術棧公眾號

日韩精品最新网址| 小早川怜子一区二区的演员表| 99久久精品久久亚洲精品| 五月花成人网| 操欧美老女人| 成人av网站在线观看| 亚洲午夜久久久久久久| 青青草视频国产| 91超薄丝袜肉丝一区二区| 大桥未久女教师av一区二区| 成人欧美一区二区三区在线播放| 91产国在线观看动作片喷水| 亚洲熟妇一区二区| gogo在线高清视频| 精品一区二区在线观看| 这里只有精品丝袜| 91香蕉视频污版| 九九九伊在人线综合| 亚洲一区观看| 亚洲国产91色在线| 给我免费播放片在线观看| 免费在线观看黄色av| 午夜精品一二三区| 久久久影院免费| 色婷婷av久久久久久久| 国产日韩三区| 亚洲激情视频一区| a看欧美黄色女同性恋| 一区二区三区在线视频观看 | 国产精品久久久久久网站| 国产人妻黑人一区二区三区| 免费在线中文字幕| 国产99久久久国产精品潘金网站| 久久亚洲精品成人| 精品人妻一区二区三区免费| 成年视频在线观看| 久久理论电影网| 国产激情久久久久| 蜜桃久久精品成人无码av| 黄色成人免费网| 久久日一线二线三线suv| 亚洲一区二区免费在线| 久草中文在线视频| 婷婷亚洲五月| 欧美一区二区黄色| 亚洲人成无码网站久久99热国产 | 91丨九色丨尤物| 久久免费精品视频| 你懂得在线视频| 欧美国产大片| 国产精品伦理一区二区| 国产在线不卡精品| 激情五月婷婷在线| 天天做综合网| 久久精品成人一区二区三区 | 成人av色网站| 亚洲婷婷综合色高清在线| 91九色露脸| 国产欧美一区二区三区在线看蜜臂| 在线日本制服中文欧美| 欧美日韩激情一区二区| 免费看日b视频| 成人免费网址| 一区二区三区在线看| 国产免费xxx| 天天操天天干天天舔| 久久一二三四| 久久国产精彩视频| 国产成人无码一区二区在线观看| 成人四虎影院| 色婷婷综合视频在线观看| 一区不卡视频| 天堂成人在线| 国产在线日韩欧美| 日本一欧美一欧美一亚洲视频| 日本成人精品视频| 亚洲美女视频| 一本久久综合亚洲鲁鲁| 年下总裁被打光屁股sp | 亚洲av成人无码网天堂| 日韩国产精品91| 欧美日韩国产999| 最近中文字幕在线mv视频在线 | 丰满的亚洲女人毛茸茸| 一区二区三区自拍视频| 欧美专区亚洲专区| 欧美成人免费在线观看视频| 调教视频免费在线观看| 99国产精品久久久久久久久久 | 欧美激情第99页| 人妻少妇无码精品视频区| 精品久久久亚洲| 亚洲电影免费观看高清完整版在线观看 | 91成人在线| 91精品国产综合久久精品| youjizz.com国产| 成年永久一区二区三区免费视频| 最新国产成人在线观看| 老司机激情视频| 韩国美女久久| 欧美一级高清片在线观看| 国产精彩免费视频| 在线女人免费视频| 亚洲大片免费看| 成人污网站在线观看| 欧美大胆a人体大胆做受| 亚洲综合视频网| 水蜜桃在线免费观看| 看黄网站在线观看| 国产精品亲子伦对白| 成年在线观看视频| 欧美日韩五区| 欧美性猛交xxxx黑人交| 成人在线观看a| 电影一区二区三| 欧美一级欧美三级| 91视频免费在观看| 亚洲午夜极品| 午夜精品福利在线观看| 国产乡下妇女做爰毛片| 日本美女一区二区| 国产精品久久久久久婷婷天堂| 亚洲男人第一天堂| k8久久久一区二区三区 | 久久男人的天堂| 亚洲影视一区二区| 老司机午夜精品| 国产日本欧美一区二区三区| 无码精品人妻一区二区三区影院| 1024国产精品| 国产成人精品视频ⅴa片软件竹菊| 538任你躁精品视频网免费| 日韩网站在线观看| 青青草原在线免费观看| 欧美福利视频| 97视频在线播放| 在线观看毛片网站| 国产调教视频一区| 中文字幕一区二区三区精彩视频| 超碰个人在线| 欧美老肥妇做.爰bbww| 在线观看一区二区三区视频| 国产成人夜色高潮福利影视 | 伊人在我在线看导航| 亚洲激情综合网| 国产精品嫩草影院8vv8 | 天堂va蜜桃一区二区三区漫画版| 国产精品一区视频网站| 午夜视频www| 亚洲成人在线免费| 成人啪啪18免费游戏链接| 牛夜精品久久久久久久99黑人| 国产在线精品自拍| 日本精品一区二区三区在线播放| 欧美专区日韩专区| 18啪啪污污免费网站| 欧美激情视频一区二区三区在线播放| 精品中文字幕在线2019| 国产孕妇孕交大片孕| jlzzjlzz亚洲日本少妇| 国产一线二线三线女| 3d性欧美动漫精品xxxx软件| 91麻豆精品国产91久久久资源速度 | 中文网丁香综合网| 亚洲精品第一| 亚洲高清福利视频| 日韩网红少妇无码视频香港| 美女视频一区在线观看| av一区二区三区四区电影| 国产视频精品久久| 亚洲综合一区二区| 久久性爱视频网站| 中文在线一区| 午夜精品一区二区在线观看| 国产美女情趣调教h一区二区| 色婷婷av一区二区三区软件| 国产三级黄色片| 国产一区二区三区精品欧美日韩一区二区三区| 中国成人亚色综合网站| 伊人久久亚洲| 欧美一区二区三区艳史| 精品二区在线观看| 欧美激情一区在线| 国产一区二区在线视频播放| 国产日本亚洲| 国语自产精品视频在线看抢先版图片| 香港三日本三级少妇66| 在线亚洲一区二区| 国产波霸爆乳一区二区| 26uuu色噜噜精品一区| 鲁一鲁一鲁一鲁一av| 男男gay无套免费视频欧美| 欧美极品欧美精品欧美视频| 一起草av在线| 亚洲电影一区二区| 精品日韩在线视频| 成人免费av网站| 麻豆视频传媒入口| 人人网欧美视频| 国内揄拍国内精品| 高清在线观看av| 欧美v日韩v国产v| 欧美另类视频在线观看| 久久亚洲综合色一区二区三区| 中文字幕免费高清在线| 日韩亚洲国产精品| 精品日产一区2区三区黄免费 | 久久免费国产视频| sese在线视频| 欧洲精品一区二区三区在线观看| 国产免费美女视频| 久久久久久久综合日本| 日韩a在线播放| 亚洲va久久久噜噜噜久久| 成人在线免费观看视视频| 98在线视频| 欧美日韩dvd在线观看| 四虎永久在线精品| 亚洲视频一二三区| 丁香花五月婷婷| 99久久国产免费看| 国产黑丝在线视频| 秋霞电影一区二区| 黑人糟蹋人妻hd中文字幕| 欧美理论在线| 在线无限看免费粉色视频| 亚洲人成777| 日韩免费黄色av| 蜜桃av在线| 欧美极品少妇xxxxⅹ喷水 | 久久久免费电影| 黄色大片在线播放| 日韩在线观看免费网站| 国产一区二区三区黄片| 欧美午夜精品久久久久久人妖| 99久久久久久久久久| 视频精品一区二区| 18岁网站在线观看| 亚洲国产影院| 日本精品二区| 亚洲高清影院| 国产精品美女久久| 亚洲电影有码| 国产精品999999| 欧美电影免费观看高清完整| 欧美在线视频网站| xxxxx日韩| 国产亚洲aⅴaaaaaa毛片| 久草在线青青草| 亚洲小视频在线观看| 精品亚洲综合| 国产亚洲在线播放| jizz在线观看视频| 一区二区在线免费视频| h视频在线免费| 色狠狠av一区二区三区香蕉蜜桃| 91最新在线| 日韩三级成人av网| caopo在线| 欧美激情第6页| xxxxx性欧美特大| 国产成人在线一区二区| 亚洲伦理影院| 成人性生交大片免费看视频直播 | 暗呦丨小u女国产精品| 国内精品不卡在线| 免费日韩视频在线观看| 久久xxxx精品视频| 欧美交换配乱吟粗大25p| 国内激情久久| 成熟丰满熟妇高潮xxxxx视频| 99re国产精品| 熟妇人妻va精品中文字幕| 蜜臀av性久久久久蜜臀aⅴ| 欧美激情第一区| 日日摸夜夜添夜夜添精品视频| 国产精品涩涩涩视频网站| 美女视频网站黄色亚洲| 九九九久久久久久久| 成人福利在线看| 免费观看a级片| 亚洲欧美日韩电影| 久久久久亚洲AV成人无在| 国产精品嫩草99a| 欧美黑人一级片| 欧美日韩中文字幕在线| 在线视频1卡二卡三卡| 日韩三级在线观看| 国产专区在线| 久久国产精品久久久久| 欧美xxxhd| 91超碰rencao97精品| 日韩三级av| 国产一级精品aaaaa看| 久久综合影院| 狠狠干视频网站| 天堂成人国产精品一区| 麻豆tv在线观看| 国产网站一区二区| 麻豆一区二区三区精品视频| 亚洲激情综合网| 国产第一页在线观看| 一本色道久久综合狠狠躁的推荐| 亚洲天堂狠狠干| 日韩av在线免费| 天堂在线观看av| 日韩中文字幕网| 97se综合| 国产精品久久久久久久久久久久冷 | 91精品国产色综合久久不卡电影| 手机看片福利在线| 日韩一级黄色av| 国产不卡网站| 国产一区免费在线| 综合激情网站| 91欧美视频在线| 久久久久99精品国产片| 国产精品成人免费一区二区视频| 亚洲最大色网站| 91麻豆国产视频| 亚洲午夜精品久久久久久久久久久久 | 日韩在线精品强乱中文字幕| 亚洲综合最新在线| 波多野结衣在线观看一区二区| 国产精品久久..4399| 国产精品77777| 国产黑丝一区二区| 亚洲精品视频观看| 国产又粗又猛又爽又黄的| 亚洲午夜色婷婷在线| 厕沟全景美女厕沟精品| 韩国一区二区三区美女美女秀| 欧美一区精品| 五月六月丁香婷婷| 综合久久一区二区三区| 中文字幕在线观看视频一区| 欧美精品三级在线观看| www免费网站在线观看| 日本一区二区不卡| 同性恋视频一区| 一女被多男玩喷潮视频| 成人高清免费观看| 日本三级网站在线观看| 亚洲精品在线观| 国产三级电影在线| 欧美有码在线观看| 亚洲自拍都市欧美小说| 黄色片视频在线免费观看| 麻豆精品视频在线| 一级在线观看视频| 欧美日韩一区成人| 蜜桃91麻豆精品一二三区| 亚洲精品suv精品一区二区| 国产乱视频在线观看| 国产成人av在线| 欧美精选一区二区三区| 五月天亚洲视频| 福利91精品一区二区三区| 久久97人妻无码一区二区三区| 日韩一区二区三区视频| 天堂av最新在线| 国产亚洲福利社区| 久久在线91| 国产日产在线观看| 欧美一区二区三区视频在线| 污污视频在线看| 精品国产一区二区三区麻豆免费观看完整版 | 丰满熟女人妻一区二区三| 日韩精品最新网址| 91九色美女在线视频| 国产在线播放不卡| 午夜视频精品| 国产精品1000部啪视频| 欧美手机在线视频| 成码无人av片在线观看网站| 国产精品露出视频| 老司机精品久久| 夫妻性生活毛片| 亚洲国产精品小视频| 深夜视频一区二区| 国产91porn| 久久影院电视剧免费观看| 伊人亚洲综合网| 欧美激情亚洲另类| 国产成人久久| 成人在线免费观看av| 欧美经典三级视频一区二区三区| 91在线精品入口| 中文字幕一区二区三区精华液 | 久99久在线视频| 卡一精品卡二卡三网站乱码| 中国人体摄影一区二区三区| 福利一区福利二区| 无码无套少妇毛多18pxxxx| 亚洲激情第一页| a成人v在线| 福利视频一区二区三区四区| 欧美国产精品中文字幕| 国产精品免费精品一区| 日韩精品免费电影|