java.lang.Integer源碼分析

Integer

本文源碼基于JDK8

Integer也是我們經(jīng)常使用的工具類、包裝類,此文主要用于記錄學(xué)習(xí)筆記,主要從源碼角度深入了解一下。

public final class Integer extends Number implements Comparable<Integer> {
    // 2147483647
    public static final int   MIN_VALUE = 0x80000000;
    // -2147483648
    public static final int   MAX_VALUE = 0x7fffffff;

    // 獲取基本類型int類型是class
    public static final Class<Integer>  TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
}

說(shuō)明:Integer.TYPE == int.class // true

  • 繼承Number類

Number類中只有構(gòu)造方法和幾個(gè)抽象方法:


這里寫圖片描述

構(gòu)造方法

public Integer(int value) {
    this.value = value;
}
public Integer(String s) throws NumberFormatException {
    this.value = parseInt(s, 10);
}

自動(dòng)裝箱和自動(dòng)拆箱

JDK1.5之后,java提供了自動(dòng)裝箱和自動(dòng)拆箱的功能,下面從源碼角度分析下Integer的裝箱:

package com.quancheng;
public class ClassTest {
    public static void main(String[] args) throws InterruptedException {
        Integer num = 10;
    }
}

通過(guò)javap -v ClassTest.class查看字節(jié)碼,可以看出自動(dòng)裝箱實(shí)際是JVM編譯器幫我們做的工作,調(diào)用的是Integer.valueOf()方法

  public static void main(java.lang.String[]) throws java.lang.InterruptedException;
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=2, args_size=1
         0: bipush        10
         2: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         5: astore_1
         6: return

分析到這里可以看出,實(shí)際上Integer a = 100 等價(jià)于Integer a = Integer.valueOf(100);只不過(guò)這個(gè)工作是JVM幫我們做的;

自動(dòng)拆箱:

public static void main(String[] args) throws InterruptedException {
    int num = new Integer(11);
}

對(duì)應(yīng)的字節(jié)碼指令:

public static void main(java.lang.String[]) throws java.lang.InterruptedException;
  descriptor: ([Ljava/lang/String;)V
  flags: ACC_PUBLIC, ACC_STATIC
  Code:
    stack=3, locals=2, args_size=1
       0: new           #2                  // class java/lang/Integer
       3: dup
       4: bipush        11
       6: invokespecial #3                  // Method java/lang/Integer."<init>":(I)V
       9: invokevirtual #4                  // Method java/lang/Integer.intValue:()I
      12: istore_1
      13: return

通過(guò)分析可以發(fā)現(xiàn),自動(dòng)拆箱實(shí)際是編譯器調(diào)用了Integer.intValue()的方法完成的轉(zhuǎn)換

重點(diǎn)方法

  • valueOf方法

    public static Integer valueOf(int i) {
      if (i >= IntegerCache.low && i <= IntegerCache.high)
          return IntegerCache.cache[i + (-IntegerCache.low)];
      return new Integer(i);
    }
    

    IntegerCache是一個(gè)靜態(tài)內(nèi)部類,主要用于緩存low - high之間數(shù)字的包裝類

    private static class IntegerCache {
      static final int low = -128;
      static final int high;
      static final Integer cache[];
    
      static {
          // high value may be configured by property
          int h = 127;
          String integerCacheHighPropValue =
              sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
          if (integerCacheHighPropValue != null) {
              try {
                  int i = parseInt(integerCacheHighPropValue);
                  i = Math.max(i, 127);
                  // Maximum array size is Integer.MAX_VALUE
                  h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
              } catch( NumberFormatException nfe) {
                  // If the property cannot be parsed into an int, ignore it.
              }
          }
          high = h;
    
          cache = new Integer[(high - low) + 1];
          int j = low;
          for(int k = 0; k < cache.length; k++)
              cache[k] = new Integer(j++);
    
          // range [-128, 127] must be interned (JLS7 5.1.7)
          assert IntegerCache.high >= 127;
      }
    
      private IntegerCache() {}
    }
    

    上面的源碼中可以看出IntegerCache有三個(gè)被final修飾的靜態(tài)filed外加一個(gè)靜態(tài)塊和一個(gè)私有的構(gòu)造器;很簡(jiǎn)單很普通的一個(gè)類,被緩存的包裝類就介于low - high之間,low的值已經(jīng)寫死-128,而high的值由你的虛擬機(jī)決定sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"),既然是一個(gè)參數(shù)也就意味著你可以動(dòng)態(tài)設(shè)置,具體怎么設(shè)置自行百度。然后在循環(huán)中將low - high之間數(shù)字的裝箱后方法cache[]這個(gè)Integer類型的數(shù)組中。這樣就完成了緩存

在日常編碼中,我們需要注意Integer緩存的問(wèn)題

Integer a = 100;
Integer b = 100;
Integer f = Integer.valueOf(100);

Integer c = 200;
Integer d = 200;

System.out.println(a == b);//true
System.err.println(a == f); // true
System.out.println(c == d);//false
  • stringSize(int x)
    這個(gè)方法很有意思,我覺(jué)得可以單獨(dú)看看這個(gè)方法,主要作用就是判斷一個(gè)數(shù)字的位數(shù),但是運(yùn)用的非常巧妙
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                      99999999, 999999999, Integer.MAX_VALUE };

// Requires positive x
static int stringSize(int x) {
    for (int i=0; ; i++)
        if (x <= sizeTable[i])
            return i+1;
}
  • equals(Object obj)

需要注意的是Integer也重寫了equals(Object obj),故若比較的值類型都是Integer時(shí),equals()和==作用是相同的

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}
我們可以寫個(gè)例子測(cè)試下:
Integer num = new Integer(999);
System.err.println(num ==999);

public static void main(java.lang.String[]) throws java.lang.InterruptedException;
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=2, args_size=1
         0: new           #2                  // class java/lang/Integer
         3: dup
         4: sipush        999
         7: invokespecial #3                  // Method java/lang/Integer."<init>":(I)V
        10: astore_1
        11: getstatic     #4                  // Field java/lang/System.err:Ljava/io/PrintStream;
        14: aload_1
        15: invokevirtual #5                  // Method java/lang/Integer.intValue:()I
        18: sipush        999
        21: if_icmpne     28
        24: iconst_1
        25: goto          29
        28: iconst_0
        29: invokevirtual #6                  // Method java/io/PrintStream.println:(Z)V
        32: return

可以看出實(shí)際上是先拆箱再比較值

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 引入 == 基本數(shù)據(jù)類型(也稱原始數(shù)據(jù)類型) :byte,short,char,int,long,float,do...
    凱諾婷閱讀 1,307評(píng)論 1 7
  • 自動(dòng)裝箱和拆箱從Java 1.5開始引入,目的是將原始類型值轉(zhuǎn)自動(dòng)地轉(zhuǎn)換成對(duì)應(yīng)的對(duì)象。自動(dòng)裝箱與拆箱的機(jī)制可以讓我...
    codersm閱讀 452評(píng)論 0 0
  • 下面的內(nèi)容是對(duì)網(wǎng)上原有的Java面試題集及答案進(jìn)行了全面修訂之后給出的負(fù)責(zé)任的題目和答案,原來(lái)的題目中有很多重復(fù)題...
    獨(dú)念白閱讀 1,494評(píng)論 0 3
  • 今天早上起來(lái)和書濤助教一起跑步,途中聽他分享課程體驗(yàn)以及課程以外的東西。感受到他的自律堅(jiān)持和高標(biāo)準(zhǔn),而他也把這些帶...
    顧鳴芬閱讀 217評(píng)論 0 1
  • 我想我真的是個(gè)假老師吧。如果暑假是從7月1日開始,那么我已經(jīng)加班三天了,據(jù)說(shuō)還要加班兩天。辦公室里無(wú)處不彌漫著工廠...
    安格麻麻閱讀 347評(píng)論 0 1

友情鏈接更多精彩內(nèi)容