最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java自動拆箱空指針異常的解決

 更新時間:2021年03月04日 10:05:34   作者:secbro2  
這篇文章主要介紹了Java自動拆箱空指針異常的解決,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

公司搬遷,臨時充當裝修工,提前兩個小時到公司忙著拆卸設(shè)備。結(jié)果接到客戶反映,某部分功能偶爾不能用。于是參與救火,與寫這段代碼的小伙伴一起排查原因。

最終發(fā)現(xiàn)導(dǎo)致業(yè)務(wù)偶爾不能使用是由Long類型自動拆箱導(dǎo)致空指針異常引起的。下面就帶大家分析一下Java中基礎(chǔ)類型的包裝類在拆箱和裝箱過程中都做了什么,為什么會出現(xiàn)空指針異常,以及面試過程中會出現(xiàn)的相關(guān)面試題。

問題重現(xiàn)

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

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類型的強轉(zhuǎn)。當接口返回的userId為null時,強轉(zhuǎn)這塊就拋出空指針異常:

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

上面的場景跟下面的代碼出現(xiàn)異常效果一樣:

public class BoxTest {

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

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

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

原因分析

最初大家可能會疑惑,拋出異常的代碼都沒有對象的方法調(diào)用,怎么會出現(xiàn)空指針呢?

這中間主要涉及到的就是一個自動拆箱操作。是否是拆箱導(dǎo)致的呢?我們來通過字節(jié)碼看一下。

通過javap -c來查看一下對應(yīng)的字節(jié)碼:

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
}

其中g(shù)etValue方法調(diào)用對應(yīng)的是main方法中編號3和6的操作。編號3為命令invokevirtual為方法指令。對應(yīng)的便是value.longValue,value對應(yīng)的就是聲明的Long類型。

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

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

對照最開始的代碼,如果value為null的話,那么在調(diào)用longValue方法時便會拋出NullPointerException。
所以,本質(zhì)上來講,所謂的自動拆箱和裝箱只不過是Java提供的語法糖而已。

再次證實

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

public class IntBoxTest {

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

同樣查看上面代碼的字節(jié)碼:

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,調(diào)用的方法為Integer.valueOf;而編號7進行了拆箱操作將Integer類型轉(zhuǎn)換成了int類型,調(diào)用的方法為Integer.intValue。

自動拆箱裝箱的本質(zhì)

通過上面的分析,我們可以看出所謂的拆箱(unboxing)和裝箱(boxing)操作只不過是一個語法糖的功能。編譯器在編譯操作時,本質(zhì)上還是會調(diào)用對應(yīng)包裝類的不同方法來進行處理。
裝箱時通常會調(diào)用包裝類的valueOf方法,而拆箱時通常會調(diào)用包裝類的xxxValue()方法,其中xxx為類似boolean/long/int等。
而自動拆箱和裝箱的操作主要發(fā)生在賦值、比較、算數(shù)運算、方法調(diào)用等常見。此時,我們就需要主要空指針的問題。

面試題

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

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

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

很明顯在調(diào)用兩個方法時都會拋出空指針異常。關(guān)于拋空指針異常的原因及分析過程,上文已經(jīng)講過,大家可以嘗試分析一下字節(jié)碼。

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

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

答案:可以正常執(zhí)行。在Java中null是一個特殊的值,可以賦值給任何引用類型,也可以轉(zhuǎn)化為任何引用類型。

小結(jié)

任何一個小的問題,小的異常,如果深入追蹤一下,不僅能夠更清楚的明白底層原理,而且還可以在實踐的過程中更有把握,更少犯錯。

到此這篇關(guān)于Java自動拆箱空指針異常的解決的文章就介紹到這了,更多相關(guān)Java自動拆箱空指針異常內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • Mybatis-plus如何查詢返回對象內(nèi)有List<String>屬性

    Mybatis-plus如何查詢返回對象內(nèi)有List<String>屬性

    在使用Mybatis-Plus進行開發(fā)時,我們經(jīng)常會遇到需要處理一對多關(guān)系映射的情況,例如,查詢用戶數(shù)據(jù)時,可能需要同時獲取該用戶管理的所有小區(qū)名稱列表,這要求我們在返回的實體類中包含一個List<String>屬性,用于存放小區(qū)名稱,實現(xiàn)這一功能
    2024-10-10
  • java中實體類和JSON對象之間相互轉(zhuǎn)化

    java中實體類和JSON對象之間相互轉(zhuǎn)化

    Java中關(guān)于Json格式轉(zhuǎn)化Object,Map,Collection類型和String類型之間的轉(zhuǎn)化在我們實際項目中應(yīng)用的很是普遍和廣泛。最近工作的過程中也是經(jīng)常有,因此,自己封裝了一個類分享給大家。
    2015-05-05
  • java String類型對象轉(zhuǎn)換為自定義類型對象的實現(xiàn)

    java String類型對象轉(zhuǎn)換為自定義類型對象的實現(xiàn)

    本文主要介紹了java String類型對象轉(zhuǎn)換為自定義類型對象的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Java反射機制概念、原理與用法總結(jié)

    Java反射機制概念、原理與用法總結(jié)

    這篇文章主要介紹了Java反射機制概念、原理與用法,較為詳細的分析了java反射機制的概念、原理,并結(jié)合實例形式總結(jié)分析了java反射機制的具體使用方法與相關(guān)注意事項,需要的朋友可以參考下
    2017-11-11
  • java實現(xiàn)建造者模式(Builder Pattern)

    java實現(xiàn)建造者模式(Builder Pattern)

    這篇文章主要為大家詳細介紹了java實現(xiàn)建造者模式Builder Pattern,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • spring利用squertz實現(xiàn)定時任務(wù)

    spring利用squertz實現(xiàn)定時任務(wù)

    spring squertz是一個強大的定時任務(wù)處理方式。下面這篇文章主要介紹了spring利用squertz實現(xiàn)定時任務(wù)的相關(guān)資料,文中介紹的很詳細,對大家具有一定的參考借鑒價值,需要的朋友們下面來一起看看吧。
    2017-01-01
  • java 線程池的實現(xiàn)原理、優(yōu)點與風(fēng)險、以及4種線程池實現(xiàn)

    java 線程池的實現(xiàn)原理、優(yōu)點與風(fēng)險、以及4種線程池實現(xiàn)

    這篇文章主要介紹了java 線程池的實現(xiàn)原理、優(yōu)點與風(fēng)險、以及4種線程池實現(xiàn)包括了:配置線程池大小配置,線程池的實現(xiàn)原理等,需要的朋友可以參考下
    2023-02-02
  • Java?Web項目中解決中文亂碼方法總結(jié)(三種最新方法)

    Java?Web項目中解決中文亂碼方法總結(jié)(三種最新方法)

    這篇文章主要介紹了Java?Web項目中解決中文亂碼方法總結(jié),本文給大家分享三種最新解決方法,需要的朋友可以參考下
    2022-06-06
  • springboot如何獲取文件流

    springboot如何獲取文件流

    這篇文章主要介紹了springboot如何獲取文件流,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 關(guān)于Spring啟動流程及Bean生命周期梳理

    關(guān)于Spring啟動流程及Bean生命周期梳理

    這篇文章主要介紹了關(guān)于Spring啟動流程及Bean生命周期梳理,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11

最新評論

神木县| 金秀| 阳西县| 噶尔县| 叶城县| 泰和县| 永新县| 保定市| 夹江县| 淮南市| 于田县| 张家川| 综艺| 信宜市| 化德县| 崇仁县| 盐山县| 利川市| 辽宁省| 富源县| 舟曲县| 雷山县| 泊头市| 禹城市| 图木舒克市| 静海县| 新建县| 新建县| 长沙县| 彭州市| 波密县| 龙胜| 农安县| 宿迁市| 扬州市| 濮阳县| 若尔盖县| 黔西| 双鸭山市| 固阳县| 前郭尔|