天天看點

《手冊》詳解 第2節學員提問之 ==150問題解析

一、背景

碼出規範:《阿裡巴巴Java開發手冊》詳解 專欄剛釋出, 其中 “第二節 02 Integer緩存問題分析”講到:

Integer var = ? 形式聲明整型,最終會通過 java.lang.Integer#valueOf(int) 來構造整數對象。

有一個學員提出了斷點時出現  i =255問題,在另外一篇文章作了分析:

https://dwz.cn/m1of2kIu 又有一個朋友發了另外一個類似的問題:

public static void main(String[] args) {
    Integer c = 150;
    System.out.println(c==150);
}           

相信學過本專欄的同學可以快速解決這個問題。

二、問題分析

2.1  JLS 大法

根據 JLS 可知,整數對象和整數數值通過 == 比較時,會自動拆箱,比較的是數值。

If r is a reference of type Integer, then unboxing conversion converts r into r.intValue()           

2.2 反彙編大法

假裝我們不知道 JLS的規定,我們可以通過反彙編大法來檢視。

public class com.imooc.basic.learn_int.IntegerTest {
  public com.imooc.basic.learn_int.IntegerTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: sipush        150
       3: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       6: astore_1
       7: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
      10: aload_1
      11: invokevirtual #4                  // Method java/lang/Integer.intValue:()I
      14: sipush        150
      17: if_icmpne     24
      20: iconst_1
      21: goto          25
      24: iconst_0
      25: invokevirtual #5                  // Method java/io/PrintStream.println:(Z)V
      28: return
}           

核心邏輯:

看到行數為 17的地方,将 intValue 和 150 整數值比較,如果不相等跳轉到 24行,

24行将常量0入棧 (虛拟機中用0 可以表示false),然後調用參數為 boolean類型(Z)的列印語句列印,。

如果相等,繼續執行到20行,将常量1入棧,然後調用參數為 boolean類型(Z)的列印語句。

反向翻譯成 Java源代碼大緻如下:

public static void main(String[] args) {
    Integer c = 150;
    if(c.intValue() == 150){
        System.out.println(true);
    }else{
        System.out.println(false);
    }
}           

是以答案就非常顯而易見了。

在這裡希望大家能夠自主學習  《Java虛拟機規範》,反彙編後能夠有自行腦補出對應的Java代碼的能力。

Java語言手冊和虛拟機手冊官方版下載下傳:

https://docs.oracle.com/javase/specs/index.html

大家如果看英文吃力,也可以自行購買中文翻譯版。

2.3 代碼調試法

我們可以在構造方法上和valueOf上打斷點,看看來自自己源碼調用時 參數為150的調用有幾次,可以觀察到隻有一次。

另外我們還可以檢視記憶體中構造的值為 150的整數對象個數。

可以從右下角的 memory 頁籤中搜尋 Integer ,然後輕按兩下後使用表達式  equals(150)來檢視,值為 150的整數對象,最後發現就一個。

《手冊》詳解 第2節學員提問之 ==150問題解析

是以第二個 150并沒有轉成整數對象。

建議大家可以掌握這種檢視記憶體對象的方法,當沒有聲明引用時無法通過變量視窗檢視時,可以采用此方法核實。

專欄後續的代碼調試小節将講述如異常斷點,遠端調試等更多調試技巧。

三、總結

1 通過《《手冊》詳解 第2節學員提問之斷點 i=255問題解析 》 和本小節,大家可以發現,記憶知識容易遺忘,而方法才是通用的,掌握常見的經典的好方法可以用來解決很多同類的問題。

2 希望大家以後可以養成分析問題的習慣,遇到類似問題時可以快速解決,而不是搜尋各種部落格,詢問别人。

希望大家能夠自主學習,知其然又知其是以然。

3 專欄還會介紹更多學習和排錯技巧,感興趣的同學可以關注專欄。連結:

https://dwz.cn/2GIxxC9n

相關文章

1Integer 緩存問題分析

2《手冊》詳解 第2節學員提問之斷點 i=255問題解析