JDK 8与JDK 10:三元/拆箱的区别
最近的Nicolai Parlog ( @nipafx ) 鳴叫引起了我的注意,因為它引用了關于JDK 8和JDK 10之間行為更改的有趣StackOverflow討論 ,并詢問“為什么?” SerCe 在StackOverflow線程上引用的問題最終歸結為在JDK 8和JDK 10之間更改了實現,以正確實現 Java語言規范。
下面的代碼清單(略有改編)改編自SerCe在StackOverflow線程上提供的原始示例。
在JDK 10和JDK 8中表現不同的改編示例
public static void demoSerCeExample() {try{final Double doubleValue = false ? 1.0 : new HashMap<String, Double>().get("1");out.println("Double Value: " + doubleValue);}catch (Exception exception){out.println("ERROR in 'demoSerCeExample': " + exception);} } 使用JDK 8編譯并執行上述代碼后,它將生成如下輸出:
Double Value: null
使用JDK 10編譯并執行上述代碼后,它將生成如下輸出: ERROR in 'demoSerCeExample': java.lang.NullPointerException 在JDK 8中,三元運算符返回null以便分配給局部變量doubleValue ,但在JDK 10中,為同一三元語句拋出NullPointerException 。
此示例的兩個調整導致一些有趣的觀察。 首先,如果將三元運算符中表示的文字常量1.0指定為Double.valueOf(1.0) ,則JDK 8和JDK 10都將局部變量設置為null而不是拋出NullPointerException 。 其次,如果使用原始類型double而不是引用類型Double聲明了局部變量,則無論Java版本和是否使用Double.valueOf(double)都始終拋出NullPointerException 。 當然,第二個觀察是有道理的,因為無論三元運算符如何處理對象或引用,都必須在某個點取消引用以將其分配給原始double類型,并且在示例中始終會導致NullPointerException 。
下表總結了這些觀察結果:
| 完整的三元聲明 | 設置局部變量doubleValue | |
| JDK 8 | JDK 10 | |
| Double doubleValue = false ? 1.0 : new HashMap<String, Double>().get("1"); | null | NullPointerException |
| double doubleValue= false? 1.0: new HashMap<String, Double>().get("1"); | NullPointerException | NullPointerException |
| Double doubleValue= false? Double.valueOf(1.0): new HashMap<String, Double>().get("1"); | null | null |
| double doubleValue= false? Double.valueOf(1.0): new HashMap<String, Double>().get("1"); | NullPointerException | NullPointerException |
對于這個一般的三進制示例,在兩個Java版本中都避免NullPointerException的唯一方法是將局部變量聲明為引用類型Double (無需取消裝箱)并使用Double.valueOf(double)以便在整個過程中都使用引用Double三元而不是原始的double 。 如果僅通過指定1.0隱含原始double ,則Java Map返回的Double在JDK 10中將被隱式取消裝箱(取消引用),并導致異常。 根據Brian Goetz的說法 ,JDK 10使實現返回到符合規范的狀態。
翻譯自: https://www.javacodegeeks.com/2018/06/jdk-ternary-difference.html
總結
以上是生活随笔為你收集整理的JDK 8与JDK 10:三元/拆箱的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关注这几个元素,雨天也能拍出不亚于晴天的
- 下一篇: api签名_使用签名保护基于HTTP的A