国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

你真的會用 Java 中的三目運算符嗎?

2019-11-08 00:27:17
字體:
供稿:網(wǎng)友

轉(zhuǎn)載:http://blog.jobbole.com/93511/

寫在前面:

三目運算符是我們經(jīng)常在代碼中使用的,a= (b==null?0:1); 這樣一行代碼可以代替一個 if-else,可以使代碼變得清爽易讀。但是,三目運算符也是有一定的語言規(guī)范的。在運用不恰當(dāng)?shù)臅r候會導(dǎo)致意想不到的問題。前段時間遇到(一個由于使用三目運算符導(dǎo)致的問題,其實是因為有三目運算符和自動拆箱同時使用(雖然自動拆箱不是我主動用的)。

一、三目運算符

對于條件表達式b?x:y,先計算條件b,然后進行判斷。如果b的值為true,計算x的值,運算結(jié)果為x的值;否則,計算y的值,運算結(jié)果為y的值。一個條件表達式從不會既計算x,又計算y。條件運算符是右結(jié)合的,也就是說,從右向左分組計算。例如,a?b:c?d:e將按a?b:(c?d:e)執(zhí)行。

二、自動裝箱與自動拆箱

基本數(shù)據(jù)類型的自動裝箱(autoboxing)、拆箱(unboxing)是自J2SE 5.0開始提供的功能。 一般我們要創(chuàng)建一個類的對象實例的時候,我們會這樣:Class a = new Class(parameters); 當(dāng)我們創(chuàng)建一個Integer對象時,卻可以這樣:Integer i = 100;(注意:和 int i = 100;是有區(qū)別的 ) 實際上,執(zhí)行上面那句代碼的時候,系統(tǒng)為我們執(zhí)行了:Integer i = Integer.valueOf(100); 這里暫且不討論這個原理是怎么實現(xiàn)的(何時拆箱、何時裝箱),也略過普通數(shù)據(jù)類型和對象類型的區(qū)別。我們可以理解為,當(dāng)我們自己寫的代碼符合裝(拆)箱規(guī)范的時候,編譯器就會自動幫我們拆(裝)箱。那么,這種不被程序員控制的自動拆(裝)箱會不會存在什么問題呢?

三、問題回顧

首先,通過你已有的經(jīng)驗看一下下面這段代碼。如果你得到的結(jié)果和后文分析的結(jié)果一致(并且你知道原理),那么請忽略本文。如果不一致,請跟我探索下去。

java
12Map<String,Boolean>map =  newHashMap<String,Boolean>();Boolean b= (map!=null? map.get("test"): false);

以上這段代碼,是我們在不注意的情況下有可能經(jīng)常會寫的一類代碼(在很多時候我們都愛使用三目運算符)。當(dāng)然,這段代碼是存在問題的,執(zhí)行該代碼,會報NPE.

1Exceptionin thread"main" java.lang.NullPointerException

首先可以明確的是,既然報了空指針,那么一定是有些地方調(diào)用了一個null的對象的某些方法。在這短短的兩行代碼中,看上去只有一處方法調(diào)用map.get("test"),但是我們也都是知道,map已經(jīng)事先初始化過了,不會是Null,那么到底是哪里有空指針呢。我們接下來反編譯一下該代碼。看看我們寫的代碼在經(jīng)過編譯器處理之后變成了什么樣。

反編譯后代碼如下:

Java
12HashMaphashmap =new HashMap();Boolean boolean1= Boolean.valueOf(hashmap== null? false: ((Boolean)hashmap.get("test")).booleanValue());

看完這段反編譯之后的代碼之后,經(jīng)過分析我們大概可以知道問題出在哪里。((Boolean)hashmap.get("test")).booleanValue()的執(zhí)行過程及結(jié)果如下:

hashmap.get(“test”)->null;

(Boolean)null->null;

null.booleanValue()->報錯

好,問題終于定位到了。那么接下來看看如何解決該問題以及為什么會出現(xiàn)這種問題。

四、原理分析

通過查看反編譯之后的代碼,我們準(zhǔn)確的定位到了問題,分析之后我們可以得出這樣的結(jié)論:NPE的原因應(yīng)該是三目運算符和自動拆箱導(dǎo)致了空指針異常。

那么,這段代碼為什么會自動拆箱呢?這其實是三目運算符的語法規(guī)范。參見jls-15.25,摘要如下:

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.

If one of the second and third operands is of the null type and the type of the other is a reference type, then the type of the conditional expression is that reference type.

簡單的來說就是:當(dāng)?shù)诙谌徊僮鲾?shù)分別為基本類型和對象時,其中的對象就會拆箱為基本類型進行操作。

所以,結(jié)果就是:由于使用了三目運算符,并且第二、第三位操作數(shù)分別是基本類型和對象。所以對對象進行拆箱操作,由于該對象為null,所以在拆箱過程中調(diào)用null.booleanValue()的時候就報了NPE。

五、問題解決

如果代碼這么寫,就不會報錯:

Java
12Map<String,Boolean>map=  newHashMap<String,Boolean>();Boolean b= (map!=null? map.get("test"): Boolean.FALSE);

就是保證了三目運算符的第二第三位操作數(shù)都為對象類型。

這和三目運算符有關(guān)。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 通化县| 大渡口区| 汝州市| 宁强县| 黎川县| 民丰县| 融水| 三河市| 成都市| 沙河市| 定南县| 常德市| 邛崃市| 南昌县| 高阳县| 吕梁市| 遵义县| 辰溪县| 苍山县| 洛浦县| 张掖市| 武川县| 霸州市| 环江| 会东县| 东兰县| 仁寿县| 苏尼特右旗| 壤塘县| 安新县| 出国| 泊头市| 长子县| 大英县| 兴山县| 浦江县| 四川省| 德保县| 家居| 黄浦区| 通城县|