Java 中 Integer 源碼學習之緩存池了解

2022-01-24 R先生專欄

收錄於話題 #java 4個

Java 中 Integer 源碼學習之緩存池了解 面試題 new Integer(123) 與 Integer.valueOf(123) 的區別?new Integer(123) 每次都會新建一個對象;Integer.valueOf(123) 會使用緩存池中的對象,多次調用會取得同一個對象的引用。
        Integer a = new Integer(125);
        Integer b = new Integer(125);
        // false
        System.out.println(a == b);
        Integer c = Integer.valueOf(125);
        Integer d = Integer.valueOf(125);
        // true
        System.out.println(c == d );

這裡不討論包裝類型間的相等判斷應該用equals,而不是'==';

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

Integer.valueOf() 方法的實現比較簡單,第一步先判斷值是否在緩存池中,如果在的話就直接返回緩存池的內容。

那麼,在 Java 8 中 Integer 中緩存池默認大小是多少呢?答案是 -128~127;編譯器會在緩衝池範圍內的基本類型自動裝箱過程調用 valueOf() 方法,因此多個 Integer 實例使用自動裝箱來創建並且值相同,那麼就會引用相同的對象。

        Integer a = 125;
        Integer b = 125;
        // true
        System.out.println(a == b);

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() {}
    }

所以我們在使用 Int 類型對應的包裝類型時,就可以直接使用緩衝池中的對象。

結束語

何為目的?人生根本沒有目的,何況工作呢。

- END -

相關焦點

  • 理解Java Integer的緩存策略
    首先看一個使用 Integer 的示例代碼,展示了 Integer 的緩存行為。接著我們將學習這種實現的原因和目的。你可以先猜猜下面 Java 程序的輸出結果。很明顯,這裡有一些小陷阱,這也是我們寫這篇文章的原因。大多數人都認為上面的兩個判斷的結果都是 false。雖然它們的值相等,但由於比較的是對象,而對象的引用不一樣,所以會認為兩個 if 判斷都是 false 的。
  • 吊打面試官系列:說說Integer緩存範圍
    可以通過系統屬性來獲得:-Djava.lang.Integer.IntegerCache.high=<size>     */   private static class IntegerCache {        static final int low = -128;        static final int high;        //使用數組來緩存常量池
  • java面試技巧:Integer和int的那些事
    先我們來看如下的些試連環炮:開發中你在定義常量的時候,般是的Integer還是int,他們之間有什麼區別?什麼叫包裝類,它是如何包裝基本類型的?Integer的動裝箱和動拆箱的原理是什麼?以及所發在哪個階段?帶來的好處和壞處是什麼? 什麼情況下會發動裝箱/動拆箱?那你能說下Integer的值緩存是什麼嗎?你覺得 Integer的源碼有哪些設計要點?
  • 你真的理解 Integer 的緩存問題嗎?|CSDN 博文精選
    問原因則隨口就說」Integer緩存了-128到127之間的整數對象「,為什麼會緩存?還有其他答案?可能就不知道了。what??? 難道這不是標準答案?還想咋地?分析運行想知道答案很容易,直接運行,結果是 true ,false。
  • Java中常用的七個阻塞隊列第二篇DelayQueue源碼介紹
    Java中常用的七個阻塞隊列第二篇DelayQueue源碼介紹通過前面兩篇文章,我們對隊列有了了解及已經認識了常用阻塞隊列中的三個了。本篇我們繼續介紹剩下的幾個隊列。本文主要內容:通過源碼學習Delayqueue及理解Dqueue並用代碼簡單演示使用場景。
  • JAVA上百實例源碼以及開源項目
    java求一個整數的因子Java生成密鑰的實例1個目標文件摘要:Java源碼,算法相關,密鑰  Java生成密鑰、保存密鑰的實例源碼,通過本源碼可以了解到Java如何產生單鑰加密的密鑰(myKey)、產生雙鑰的密鑰對(keyPair)、如何保存公鑰的字節數組、保存私鑰到文件privateKey.dat、如何用Java對象序列化保存私鑰,通常應對私鑰加密後再保存
  • int 和 integer:裝箱和拆箱的過程,會用到什麼方法
    包裝類均位於java.lang包,包裝類和基本數據類型的對應關係如下表所示在這八個類名中,除了Integer和Character類以後,其它六個類的類名和基本數據類型一致,只是類名的第一個字母大寫即可。
  • 通過本質看現象:關於Integer受內部初始範圍而出現的有趣現象
    在我們現實生活中,人們總說要透過現象去看本質,但若能反過來通過本質來分析現象,我想,同樣可以深入理解很多東西。就像你能讀懂一個人,就會很容易理解這個人的所作所為。打一個比方,你要弄懂一個人為何要犯罪,首先得了解他做這件事的心理,這就是通過本質回過頭去看現象。這道題,如果能通過本質來看現象,就會茅塞頓開。Integer的本質是什麼,當然是它的源碼咯。
  • Java 數據持久化系列之 HikariCP (一)
    在上一篇《Java 數據持久化系列之池化技術》中,我們了解了池化技術,並使用 Apache-common-Pool2 實現了一個簡單連接池,實驗對比了它和 HikariCP、Druid 等資料庫連接池的性能數據。在性能方面,HikariCP遙遙領先,而且它還是 Spring Boot 2.0 默認的資料庫連接池。下面我們就來了解一下這款明星級開源資料庫連接池的實現。
  • JAVA並發之AtomicInteger原理分析
    假設現在我們要實現多線程應用中的int值自增(單個應用範圍),應該怎麼做呢?AtomicInteger源碼分析下面我們來看下AtomicInteger內部是如何實現的呢。CAS下面是AtomicInteger類中的一個方法,它通過Unsafe對象調用了CAS功能。CAS是目前幾乎所有CPU都提供的一個功能,而且是原子操作,藉助它可以實現很多高效的功能。
  • int 和 integer :裝箱和拆箱的過程,會用到什麼方法,你覺得這個會對性能有影響嗎,原因是什麼(百度一面)
    包裝類均位於java.lang包,包裝類和基本數據類型的對應關係如下表所示在這八個類名中,除了Integer和Character類以後,其它六個類的類名和基本數據類型一致,只是類名的第一個字母大寫即可。2、為什麼需要包裝類很多人會有疑問,既然Java中為了提高效率,提供了八種基本數據類型,為什麼還要提供包裝類呢?
  • Java 數據持久化系列之 HikariCP
    試圖修改源碼,只是閱讀源碼其實很多時候無法體會到代碼為什麼實現成這樣,在有餘力的情況下修改源碼,比較實現方案,可以更好的理解實現方案,並未後續成為 commiter 打下基礎。更加遵循 JDBC 規範,在關閉 Connection 之前先關閉與之關聯的 Statement 和ResultSet 等。對 JDBC 不了解的同學可以閱讀本系列中第一篇文章。對於資料庫連接中斷的情況,HikariCP 也處理的更加出色。
  • int和Integer裝箱拆箱遇見的坑
    例子1結果1、Integer b=3;java中將3自動裝箱成Integer類型,也就是說3已經不是基本數據類型了,變成了對象,也就是引用類型。例子2源碼可以看見有個cache緩存機制,再看low和high的值
  • 架構師學習 java架構師學習需要具備哪些能力
    架構師學習 java架構師學習需要具備哪些能力2020/7/30 15:22:22 來源:法治中國 【字體:大 中 小】【收藏本頁】【列印】【關閉】核心提示:IT行業中沒有人對java不熟悉的,而java架構師是近年來很吃香的,想要進行架構師學習,需要專業的平臺進行系統性的學習才能掌握架構師必備的一些能力
  • Java包裝類入門
    當然,沒有這些包,你也能實現你的需求,但是你需要時間,今天我們主要是來學習一下包裝類。1、為什麼需要包裝類?我們知道 Java 語言是一個面向對象的程式語言,但是 Java 中的基本數據類型卻不是面向對象的,但是我們在實際使用中經常需要將基本數據類型轉換成對象,便於操作,比如,集合的操作中,這時,我們就需要將基本類型數據轉化成對象,所以就出現了包裝類。2、包裝類是什麼呢?
  • 你真的了解java的lambda嗎?- java lambda用法與源碼分析
    我們帶著這兩個疑問來進入源碼解析。源碼解析必須了解註解 @FunctionInterface上源碼:package java.lang;import java.lang.annotation.這種實現的方法是用default關鍵字來標記的(java反射中java.lang.reflect.Method#isDefault()方法用來判斷是否是default方法),例如:
  • 五分鐘的java基礎考點速記(不包含語法)
    •Integer.valueOf(x) 和 new Integer(x) 一個會使用緩存池中的對象(多次調用指向的是同一個對象) 另一個會新建一個對象•valueOf(x) 實現的方法就是判斷值是否在緩存池中,如果不在就返回,不在就new一個,然後返回。
  • Python 標準庫之 LRU 緩存實現學習
    當緩存隊列已滿時,新的元素加入隊列時,需要從現有隊列中移除一個元素,LRU 策略就是將最近最少被訪問的元素移除,從而騰出空間給新的元素。研讀 Python 3.6 中 functools.lru_cache 源碼可以發現,它是通過一個雙向鍊表加字典實現 LRU 緩存的。下面就來學習一下這個工具函數的實現。應用在深入學習該函數之前,我們可以看看它的常規用法。
  • 通過源碼解析,深入Java 線程池原理
    從池化技術到底層實現,一篇文章帶你貫通線程池技術。1、池化技術簡介在系統開發過程中,我們經常會用到池化技術來減少系統消耗,提升系統性能。一個任務從提交到執行完畢經歷過程如下:第一步:如果當前線程池中的線程數目小於corePoolSize,則每來一個任務,就會創建一個線程去執行這個任務;第二步:如果當前線程池中的線程數目>=corePoolSize,則每來一個任務,會嘗試將其添加到任務緩存隊列當中,若添加成功,
  • java新手揭秘:阿里巴巴為何禁止使用Executors來創建線程池
    當一個java新手從不斷地Curd階段跳出來之後,就會學習java的並發,並行等高階用法,自然就會用到線程、線程池,線程池的好處這裡就不做詳細解釋,你應該會學習到Executors創建線程池的四個方法, 分別是:newFixedThreadPool