對 Java Integer.valueOf() 的一些了解


從一道選擇題開始

分析

選項A

  選項A中比較的是i01和i02,Integer i01=59這里涉及到自動裝箱過程,59是整型常量,經包裝使其產生一個引用並存在棧中指向這個整型常量所占的內存,這時i01就是Integer 的引用。
  而int i02=59由於int是基本類型,所以不存在引用問題,直接由編譯器將其存放在棧中,換一句話說,i02本身就是59。那么System.out.println(i01== i02)結果任何呢?這里涉及到了拆箱的過程,因為等號一邊存在基本類型所以編譯器后會把另一邊的Integer對象拆箱成int型,這時等號兩邊比較的就是數值大小,所以是true。

好了,到了這里,你有沒有想到這樣一個問題:如果是Integer i01=59;Integer i02=59;然后System.out.println(i01== i02)的結果是?可能你會說比較數值大小所以相等啊,也有可能說等號兩邊對象引用,所以比較的是引用,又因為開辟了不同的內存空間,所以引用不同所以返回false。可是正確答案是:true.
再來看這個問題::如果是Integer i01=300;Integer i02=300;然后System.out.println(i01== i02)的結果是? 你可能說上面你不是說了true嘛,怎么還問這樣的問題,可是這次的答案是false。你是否會吃驚?大牛除外,我是小白,求不打臉!

  解析:當靠想象無法解決問題的時候,這是就要看源代碼了!!很重要!我們可以在Integer類中找到這樣的嵌套內部類IntegerCache:

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) {
                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);
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }

        private IntegerCache() {}
    }

 

這個類就是在Integer類裝入內存中時,會執行其內部類中靜態代碼塊進行其初始化工作,做的主要工作就是把一字節的整型數據(-128-127)裝包成Integer類並把其對應的引用存入到cache數組中,這樣在方法區中開辟空間存放這些靜態Integer變量,同時靜態cache數組也存放在這里,供線程享用,這也稱靜態緩存
  所以當用Integer 聲明初始化變量時,會先判斷所賦值的大小是否在-128到127之間,若在,則利用靜態緩存中的空間並且返回對應cache數組中對應引用,存放到運行棧中,而不再重新開辟內存。
  所以對於Integer i01=59;Integer i02=59;**i01 和 i02是引用並且相等都指向緩存中的數據,所以返回true。而對於**Integer i01=300;Integer i02=300;因為其數據大於127,所以虛擬機會在堆中重新new (開辟新空間)一個 Integer 對象存放300,創建2個對象就會產生2個這樣的空間,空間的地址肯定不同導致返回到棧中的引用的只不同。所以System.out.println打印出false。

 

B選項

  從上面的分析,我們已經知道Integer i01=59返回的是指向緩存數據的引用。那么Integer.valueOf(59)返回的是什么或者操作是什么呢?
  這個函數的功能就是把int 型轉換成Integer,簡單說就是裝包,那他是新創建一個對象嗎?還是像之前利用緩存的呢?有了之前的經驗,肯定想到的是利用緩存,這樣做既提高程序速度,又節約內存,何樂而不為?
來看一下源代碼:

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

 

 

很明顯跟之前的思想一致,若在-128到127范圍,直接返回該對象的引用,否則在堆中重新new 一個。
  到這,System.out.println(i01== i03)的結果毋庸置疑就是true.

選項C

  Integer.valueOf(59)返回的是已緩存的對象的引用,而Integer i04 = new Integer(59)是在堆中新開辟的空間,所以二者的引用的值必然不同,返回false,這道題呢就選C

 

選項D

  System.out.println(i02== i04) i02是整型變量,i04是引用,這里又用到了解包,虛擬機會把i04指向的數據拆箱為整型變量再與之比較,所以比較的是數值,59==59,返回true.

 

 

學習並轉載自:https://blog.csdn.net/dawn_after_dark/article/details/74154338

 對我很有幫助

感謝作者


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM