Java中整型的緩存機制

来源:http://www.cnblogs.com/8hao/archive/2016/03/08/5254255.html
-Advertisement-
Play Games

譯文出處: 張洪亮 原文出處:Java Papers 本文將介紹Java中Integer的緩存相關知識。這是在Java 5中引入的一個有助於節省記憶體、提高性能的功能。首先看一個使用Integer的示例代碼,從中學習其緩存行為。接著我們將為什麼這麼實現以及他到底是如何實現的。你能猜出下麵的Java程式


譯文出處: 張洪亮   原文出處:Java Papers

本文將介紹Java中Integer的緩存相關知識。這是在Java 5中引入的一個有助於節省記憶體、提高性能的功能。首先看一個使用Integer的示例代碼,從中學習其緩存行為。接著我們將為什麼這麼實現以及他到底是如何實現的。你能猜出下麵的Java程式的輸出結果嗎。如果你的結果和真正結果不一樣,那麼你就要好好看看本文了。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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");       } }

我們普遍認為上面的兩個判斷的結果都是false。雖然比較的值是相等的,但是由於比較的是對象,而對象的引用不一樣,所以會認為兩個if判斷都是false的。在Java中,==比較的是對象應用,而equals比較的是值。所以,在這個例子中,不同的對象有不同的引用,所以在進行比較的時候都將返回false。奇怪的是,這裡兩個類似的if條件判斷返回不同的布爾值。

上面這段代碼真正的輸出結果:

1 2 integer1 == integer2 integer3 != integer4

Java中Integer的緩存實現

在Java 5中,在Integer的操作上引入了一個新功能來節省記憶體和提高性能。整型對象通過使用相同的對象引用實現了緩存和重用。

適用於整數值區間-128 至 +127。

只適用於自動裝箱。使用構造函數創建對象不適用。

Java的編譯器把基本數據類型自動轉換成封裝類對象的過程叫做自動裝箱,相當於使用valueOf方法:

1 2 Integer a = 10; //this is autoboxing Integer b = Integer.valueOf(10); //under the hood

現在我們知道了這種機制在源碼中哪裡使用了,那麼接下來我們就看看JDK中的valueOf方法。下麵是JDK 1.8.0 build 25的實現:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /**      * 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);     }

在創建對象之前先從IntegerCache.cache中尋找。如果沒找到才使用new新建對象。

IntegerCache Class

IntegerCache是Integer類中定義的一個private static的內部類。接下來看看他的定義。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 /**    * 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迴圈實現。從低到高並創建儘可能多的整數並存儲在一個整數數組中。這個緩存會在Integer類第一次被使用的時候被初始化出來。以後,就可以使用緩存中包含的實例對象,而不是創建一個新的實例(在自動裝箱的情況下)。

實際上這個功能在Java 5中引入的時候,範圍是固定的-128 至 +127。後來在Java 6中,可以通過java.lang.Integer.IntegerCache.high設置最大值。這使我們可以根據應用程式的實際情況靈活地調整來提高性能。到底是什麼原因選擇這個-128到127範圍呢?因為這個範圍的數字是最被廣泛使用的。 在程式中,第一次使用Integer的時候也需要一定的額外時間來初始化這個緩存。

Java語言規範中的緩存行為

Boxing Conversion部分的Java語言規範(JLS)規定如下:

如果一個變數p的值是:

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

true 和 false的布爾值 (§3.10.3)

‘\u0000’至 ‘\u007f’之間的字元(§3.10.4)

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

其他緩存的對象

這種緩存行為不僅適用於Integer對象。我們針對所有的整數類型的類都有類似的緩存機制。

有ByteCache用於緩存Byte對象

有ShortCache用於緩存Short對象

有LongCache用於緩存Long對象

有CharacterCache用於緩存Character對象

ByteShortLong有固定範圍: -128 到 127。對於Character, 範圍是 0 到 127。除了Integer以外,這個範圍都不能改變。

問啊-定製化IT教育平臺,牛人一對一服務,有問必答,開發編程社交頭條 官方網站:www.wenaaa.com 下載問啊APP,參與官方懸賞,賺百元現金。

QQ群290551701 聚集很多互聯網精英,技術總監,架構師,項目經理!開源技術研究,歡迎業內人士,大牛及新手有志於從事IT行業人員進入!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在典型的CMS系統中,通常需要為某個欄目指定個友鏈地址,通過指定友鏈地址,該欄目的地址更人性化、方便記憶,也有利用於搜索引擎優化。 但在MVC中,通常需要在應用程式啟動時註冊路由規則,該路由規則又通常和控制器進行了關聯,也就是某個地址通常情況下都是有對應的控制器進行處理的。本文介紹瞭如何在MVC環境...
  • Windows平臺:Flume學習應用—Java寫日誌數據到MongoDB。
  • javaI/O流可根據流向分為輸入和輸出流,根據流數據類型可分為字元流和位元組流。 下麵用一張圖展示I/O流的劃分: 特點: 位元組流:讀到一個位元組就返回一個位元組,並且可以處理諸如MP3,avi,jpg等格式的文件。 字元流:讀到位元組時先按照編碼規則轉化,然後輸出。只能處理純文本數據。 節點流: 類型
  • 1.命名規範 本系列的第一篇,命名風格本就是有關藝術審美,沒有美與醜的絕對標準,本文難免帶有主觀選擇傾向,但是會儘量保持客觀的態度歸納幾種主流的命名風格,僅供參考。制定規範是為了方便團隊溝通和利於代碼維護,雖然並不能符合每個藝術家的胃口。對於獨立開發者,花點時間設計自己的編碼風格也是有助於提高能力的
  • 參考站點:http://www.iteye.com/problems/64517 方法executeUpdate 用於執行 INSERT、UPDATE 或 DELETE 語句以及 SQL DDL(數據定義語言)語句,例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE
  • Java反射機制是Java語言被視為準動態語言的關鍵性質。Java反射機制的核心就是允許在運行時通過Java Reflection APIs來取得已知名字的class類的相關信息,動態地生成此類,並調用其方法或修改其域(甚至是本身聲明為private的域或方法)。 也許你使用Java已經很長時間了,
  • import java.sql.*; public class TestJDBC { // orcl為oracle資料庫中的資料庫名,localhost表示連接本機的oracle資料庫 // 1521為連接的埠號 private static String url = "jdbc:oracle:t...
  • 在進行頁面提交的時候有2中方法 1: 直接<input type="submit" value="提交" name="submit"> 2: 通過js進行提交 <input type="button" id="tijiao " onclick="Dosave()">//這個地方對id不能用特殊字元
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...