Java中整型的緩存機制

本文將介紹Java中Integer的緩存相關知識。這是在Java 5中引入的一個有助于節(jié)省內(nèi)存、提高性能的功能拦键。首先看一個使用Integer的示例代碼,從中學習其緩存行為檩淋。接著我們將為什么這么實現(xiàn)以及他到底是如何實現(xiàn)的芬为。你能猜出下面的Java程序的輸出結(jié)果嗎。如果你的結(jié)果和真正結(jié)果不一樣蟀悦,那么你就要好好看看本文了媚朦。

package com.javapapers.java;

public class JavaIntegerCache {

? ? public static void main(String... strings) {

? ? ? ? Integer integer1 = 3;

? ? ? ? Integer integer2 = 3;

? ? ? ? if (integer1 == integer2)

? System.out.println("integer1 == integer2");

? ? ? ? else

? System.out.println("integer1 != integer2");

? ? ? ? Integer integer3 = 300;

? ? ? ? Integer integer4 = 300;

? ? ? ? if (integer3 == integer4)

? System.out.println("integer3 == integer4");

? ? ? ? else

? System.out.println("integer3 != integer4");

? ? }

}

我們普遍認為上面的兩個判斷的結(jié)果都是false。雖然比較的值是相等的日戈,但是由于比較的是對象莲镣,而對象的引用不一樣,所以會認為兩個if判斷都是false的涎拉。在Java中瑞侮,==比較的是對象應用,而equals比較的是值鼓拧。所以半火,在這個例子中,不同的對象有不同的引用季俩,所以在進行比較的時候都將返回false钮糖。奇怪的是,這里兩個類似的if條件判斷返回不同的布爾值酌住。

上面這段代碼真正的輸出結(jié)果:

integer1 == integer2

integer3 != integer4

Java中Integer的緩存實現(xiàn)

在Java 5中店归,在Integer的操作上引入了一個新功能來節(jié)省內(nèi)存和提高性能。整型對象通過使用相同的對象引用實現(xiàn)了緩存和重用酪我。

適用于整數(shù)值區(qū)間-128 至 +127消痛。

只適用于自動裝箱。使用構造函數(shù)創(chuàng)建對象不適用都哭。

Java的編譯器把基本數(shù)據(jù)類型自動轉(zhuǎn)換成封裝類對象的過程叫做自動裝箱秩伞,相當于使用valueOf方法:

Integer a = 10; //this is autoboxing

Integer b = Integer.valueOf(10); //under the hood

現(xiàn)在我們知道了這種機制在源碼中哪里使用了逞带,那么接下來我們就看看JDK中的valueOf方法。下面是JDK 1.8.0 build 25的實現(xiàn):

/**

? ? ?* Returns an {@code Integer} instance representing the specified

? ? ?* {@code int} value.? If a new {@code Integer} instance is not

? ? ?* required, this method should generally be used in preference to

? ? ?* the constructor {@link #Integer(int)}, as this method is likely

? ? ?* to yield significantly better space and time performance by

? ? ?* caching frequently requested values.

? ? ?*

? ? ?* This method will always cache values in the range -128 to 127,

? ? ?* inclusive, and may cache other values outside of this range.

? ? ?*

? ? ?* @param? i an {@code int} value.

? ? ?* @return an {@code Integer} instance representing {@code i}.

? ? ?* @since? 1.5

? ? ?*/

? ? public static Integer valueOf(int i) {

? ? ? ? if (i >= IntegerCache.low && i <= IntegerCache.high)

? return IntegerCache.cache[i + (-IntegerCache.low)];

? ? ? ? return new Integer(i);

? ? }

在創(chuàng)建對象之前先從IntegerCache.cache中尋找纱新。如果沒找到才使用new新建對象展氓。

IntegerCache Class

IntegerCache是Integer類中定義的一個private static的內(nèi)部類。接下來看看他的定義脸爱。

/**

? ?* Cache to support the object identity semantics of autoboxing for values between

? ?* -128 and 127 (inclusive) as required by JLS.

? ?*

? ?* The cache is initialized on first usage.? The size of the cache

? ?* may be controlled by the {@code -XX:AutoBoxCacheMax=} option.

? ?* During VM initialization, java.lang.Integer.IntegerCache.high property

? ?* may be set and saved in the private system properties in the

? ?* sun.misc.VM class.

? ?*/


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

? }

其中的javadoc詳細的說明了緩存支持-128到127之間的自動裝箱過程遇汞。最大值127可以通過-XX:AutoBoxCacheMax=size修改。 緩存通過一個for循環(huán)實現(xiàn)簿废。從低到高并創(chuàng)建盡可能多的整數(shù)并存儲在一個整數(shù)數(shù)組中勺疼。這個緩存會在Integer類第一次被使用的時候被初始化出來。以后捏鱼,就可以使用緩存中包含的實例對象执庐,而不是創(chuàng)建一個新的實例(在自動裝箱的情況下)。

實際上這個功能在Java 5中引入的時候,范圍是固定的-128 至 +127导梆。后來在Java 6中轨淌,可以通過java.lang.Integer.IntegerCache.high設置最大值。這使我們可以根據(jù)應用程序的實際情況靈活地調(diào)整來提高性能看尼。到底是什么原因選擇這個-128到127范圍呢递鹉?因為這個范圍的數(shù)字是最被廣泛使用的。 在程序中藏斩,第一次使用Integer的時候也需要一定的額外時間來初始化這個緩存躏结。

Java語言規(guī)范中的緩存行為

在Boxing Conversion部分的Java語言規(guī)范(JLS)規(guī)定如下:

如果一個變量p的值是:

-128至127之間的整數(shù)(§3.10.1)

true 和 false的布爾值 (§3.10.3)

‘’至 ‘’之間的字符(§3.10.4)

中時,將p包裝成a和b兩個對象時狰域,可以直接使用a==b判斷a和b的值是否相等媳拴。

其他緩存的對象

這種緩存行為不僅適用于Integer對象。我們針對所有的整數(shù)類型的類都有類似的緩存機制兆览。

有ByteCache用于緩存Byte對象

有ShortCache用于緩存Short對象

有LongCache用于緩存Long對象

有CharacterCache用于緩存Character對象

Byte, Short, Long有固定范圍: -128 到 127屈溉。對于Character, 范圍是 0 到 127。除了Integer以外抬探,這個范圍都不能改變子巾。

?為了讓學習變得輕松、高效小压,今天給大家免費分享一套Java教學資源线梗。幫助大家在成為Java架構師的道路上披荊斬棘。需要資料的歡迎加入學習交流群:9285怠益,05736

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仪搔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子溉痢,更是在濱河造成了極大的恐慌僻造,老刑警劉巖憋他,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孩饼,死亡現(xiàn)場離奇詭異髓削,居然都是意外死亡,警方通過查閱死者的電腦和手機镀娶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門立膛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人梯码,你說我怎么就攤上這事宝泵。” “怎么了轩娶?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵儿奶,是天一觀的道長。 經(jīng)常有香客問我鳄抒,道長闯捎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任许溅,我火速辦了婚禮瓤鼻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贤重。我一直安慰自己茬祷,他們只是感情好,可當我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布并蝗。 她就那樣靜靜地躺著祭犯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪滚停。 梳的紋絲不亂的頭發(fā)上盹憎,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天,我揣著相機與錄音铐刘,去河邊找鬼陪每。 笑死,一個胖子當著我的面吹牛镰吵,可吹牛的內(nèi)容都是我干的檩禾。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼疤祭,長吁一口氣:“原來是場噩夢啊……” “哼盼产!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起勺馆,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤戏售,失蹤者是張志新(化名)和其女友劉穎侨核,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灌灾,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡搓译,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了锋喜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片些己。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖嘿般,靈堂內(nèi)的尸體忽然破棺而出段标,到底是詐尸還是另有隱情,我是刑警寧澤炉奴,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布逼庞,位于F島的核電站,受9級特大地震影響瞻赶,放射性物質(zhì)發(fā)生泄漏赛糟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一共耍、第九天 我趴在偏房一處隱蔽的房頂上張望虑灰。 院中可真熱鬧,春花似錦痹兜、人聲如沸穆咐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽对湃。三九已至,卻和暖如春遗淳,著一層夾襖步出監(jiān)牢的瞬間拍柒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工屈暗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拆讯,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓养叛,卻偏偏與公主長得像种呐,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子弃甥,可洞房花燭夜當晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容