首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 常量池深度解析:基本類型包裝類、String、IntegerCache 源碼剖析

     編輯:Java 相關知識

Java常量池技術是 JVM 為了優化性能、減少對象創建開銷而提供的緩存機制。本文深度剖析八大基本類型包裝類常量池、String 常量池、IntegerCache 源碼實現,並通過代碼驗證自動裝箱時的緩存行為邊界。

一、基本類型包裝類常量池

驗證代碼

public class CacheDemo {
    public static void main(String[] args) {
        // Integer 緩存範圍驗證
        Integer i1 = 100, i2 = 100;  // 自動裝箱調用 Integer.valueOf(100)
        Integer i3 = 128, i4 = 128;
        System.out.println("100 == 100 ? " + (i1 == i2)); // true
        System.out.println("128 == 128 ? " + (i3 == i4)); // false
        
        // 其他類型
        Character c1 = 'a', c2 = 'a';  // true (0-127)
        Boolean b1 = true, b2 = true;  // true
        Double d1 = 1.0, d2 = 1.0;     // false (無緩存)
    }
}

二、IntegerCache 源碼剖析 (JDK 1.8)

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

private static class IntegerCache {
    static final int low = -128;
    static final int high;  // 可通過 -Djava.lang.Integer.IntegerCache.high=xxx 調整
    static final Integer[] cache;
    
    static {
        int h = 127;
        String prop = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (prop != null) {
            int v = Long.decode(prop).intValue();
            h = Math.max(v, 127);
            h = Math.min(h, Integer.MAX_VALUE - (-low) - 1);
        }
        high = h;
        cache = new Integer[(high - low) + 1];
        for (int k = 0; k < cache.length; k++)
            cache[k] = new Integer(low + k);
    }
    private IntegerCache() {}
}

關鍵點:

  • 靜態代碼塊初始化緩存數組,佔用極少內存(~1KB)
  • high 可通過 JVM 參數調大,low 固定 -128
  • 自動裝箱 Integer i = 100 編譯為 Integer.valueOf(100)

三、String 常量池

特殊性

  • JDK 7 起移至堆內存(原在永久代/元空間),受 GC 管理
  • 兩種入池方式:
    1. 字面量聲明:String s = "abc"; 編譯期入池
    2. 手動入池:String s = new String("abc").intern(); 運行期入池
  • intern() 語義:池中有則返回引用,否則放入並返回引用

經典面試題

String s1 = "ab";
String s2 = "a" + "b";        // 編譯期常量折疊 → "ab" → 池中同一引用
String s3 = new String("ab"); // 堆中新對象
String s4 = s3.intern();      // 返回池中 "ab" 引用

System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(s1 == s4); // true
System.out.println(s3 == s4); // false

四、常見誤區與最佳實踐

  1. 誤區:Integer i = 200; Integer j = 200; i == j 為 true → 錯,超出緩存範圍各自 new
  2. 誤區:String s = new String("a") + new String("b"); s.intern() == "ab" → JDK 7+ 為 true(池中無則放入堆對象引用),JDK 6 為 false(複製到永久代)
  3. 最佳實踐:
    • 優先使用字面量 "text" 而非 new String("text")
    • 大量字符串拼接用 StringBuilder
    • 需比較內容用 equals(),== 僅比較引用
    • 調整緩存範圍:-XX:AutoBoxCacheMax=2000(部分 JVM 支持)

五、總結

常量池是 JVM「以空間換時間」的經典體現。基本類型包裝類緩存 -128~127、String 池存儲字面量與手動入池對象、IntegerCache 可配置上限。理解緩存邊界與 intern() 行為,能避免自動裝箱/字符串操作中的性能陷阱與邏輯 Bug。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
包裝類緩存範圍實現類
Byte-128 ~ 127ByteCache
Short-128 ~ 127ShortCache
Integer-128 ~ 127IntegerCache
Long-128 ~ 127LongCache
Character0 ~ 127 (\\u0000-\\u007F)CharacterCache
Booleantrue/false 兩個實例Boolean.TRUE/FALSE
Float/Double無緩存每次 new