91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中自動拆箱空指針異常如何解決

發布時間:2021-06-30 17:51:02 來源:億速云 閱讀:276 作者:Leah 欄目:編程語言

Java中自動拆箱空指針異常如何解決,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

問題重現

下面通過一個簡單的示例才重現一下異常出現的場景。

public class BoxTest {

  public static void main(String[] args) {
    Map<String,Object> result = httpRequest();
    long userId = (Long) result.get("userId");
  }

  // 模擬一個HTTP請求
  private static Map<String,Object> httpRequest(){
    Map<String,Object> map = new HashMap<>();
    map.put("userId",null);
    return map;
  }
}

基本的場景就是請求一個接口,去接口中取某個值,這個值為Long類型,從Map中取得值之后,進行Long類型的強轉。當接口返回的userId為null時,強轉這塊就拋出空指針異常:

Exception in thread "main" java.lang.NullPointerException at com.choupangxia.box.BoxTest.main(BoxTest.java:15)

上面的場景跟下面的代碼出現異常效果一樣:

public class BoxTest {

  public static long getValue(long value) {
    return value;
  }

  public static void main(String[] args) {
    Long value = null;
    getValue(value);
  }
}

上述代碼也是將Long類型進拆箱導致的異常,只不過一個在代碼中,一個在參數中。為了分析更簡化,我們以第二個為例進行講解。

原因分析

最初大家可能會疑惑,拋出異常的代碼都沒有對象的方法調用,怎么會出現空指針呢? 這中間主要涉及到的就是一個自動拆箱操作。是否是拆箱導致的呢?我們來通過字節碼看一下。

通過javap -c來查看一下對應的字節碼:

public class com.choupangxia.box.BoxTest {
 public com.choupangxia.box.BoxTest();
  Code:
    0: aload_0
    1: invokespecial #1         // Method java/lang/Object."<init>":()V
    4: return

 public static long getValue(long);
  Code:
    0: lload_0
    1: lreturn

 public static void main(java.lang.String[]);
  Code:
    0: aconst_null
    1: astore_1
    2: aload_1
    3: invokevirtual #2         // Method java/lang/Long.longValue:()J
    6: invokestatic #3         // Method getValue:(J)J
    9: pop2
   10: return
}

其中getValue方法調用對應的是main方法中編號3和6的操作。編號3為命令invokevirtual為方法指令。對應的便是value.longValue,value對應的就是聲明的Long類型。

也就是說編譯器將getValue(value)拆分成了兩步,第一步將通過value的longValue方法將其拆箱,然后再將拆箱之后的結果傳遞給方法。相當于:

long primitive = value.longValue();
test(promitive);

對照最開始的代碼,如果value為null的話,那么在調用longValue方法時便會拋出NullPointerException.

所以,本質上來講,所謂的自動拆箱和裝箱只不過是Java提供的語法糖而已。

再次證實

下面用int類型的實例同時證實一下自動拆箱和自動裝箱兩個操作語法糖底層到底是怎么運行的:

public class IntBoxTest {

  public static void main(String[] args) {
    Integer index = 11;
    int primitive = index;
  }
}

同樣查看上面代碼的字節碼:

public class com.choupangxia.box.IntBoxTest {
 public com.choupangxia.box.IntBoxTest();
  Code:
    0: aload_0
    1: invokespecial #1         // Method java/lang/Object."<init>":()V
    4: return

 public static void main(java.lang.String[]);
  Code:
    0: bipush    11
    2: invokestatic #2         // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
    5: astore_1
    6: aload_1
    7: invokevirtual #3         // Method java/lang/Integer.intValue:()I
   10: istore_2
   11: return
}

可以看到main方法部分,編號2進行了裝箱操作,將原始類型int,裝箱成了Integer,調用的方法為Integer.valueOf;而編號7進行了拆箱操作將Integer類型轉換成了int類型,調用的方法為Integer.intValue。

自動拆箱裝箱的本質

通過上面的分析,我們可以看出所謂的拆箱(unboxing)和裝箱(boxing)操作只不過是一個語法糖的功能。編譯器在編譯操作時,本質上還是會調用對應包裝類的不同方法來進行處理。

裝箱時通常會調用包裝類的valueOf方法,而拆箱時通常會調用包裝類的xxxValue()方法,其中xxx為類似boolean/long/int等。

而自動拆箱和裝箱的操作主要發生在賦值、比較、算數運算、方法調用等常見。此時,我們就需要主要空指針的問題。

面試題

看一個面試題:請問下面foo1和foo2被調用時如何執行?并簡單分析一下。

public void foo1() {
  if ((Integer) null == 1) {
  }
}

public void foo2() {
  if ((Integer) null > 1) {
    System.out.println("abc");
  }
}

很明顯在調用兩個方法時都會拋出空指針異常。關于拋空指針異常的原因及分析過程,上文已經講過,大家可以嘗試分析一下字節碼。

再看一個面試題:下面的語句能正常執行嗎?

Integer value1 = (Integer) null;
Double value2 = (Double) null;
Boolean value3 = (Boolean) null;

看完上述內容,你們掌握Java中自動拆箱空指針異常如何解決的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

柏乡县| 义乌市| 四子王旗| 梓潼县| 马山县| 莱州市| 平和县| 科技| 盐边县| 龙南县| 新营市| 道孚县| 黑龙江省| 仲巴县| 南皮县| 确山县| 富蕴县| 上饶市| 石城县| 宁乡县| 剑川县| 新和县| 丰台区| 六安市| 呼玛县| 麦盖提县| 肃北| 上高县| 柘城县| 宁津县| 芜湖县| 清徐县| 息烽县| 金阳县| 龙泉市| 汽车| 宜良县| 梁山县| 屏边| 龙江县| 麻江县|