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

Java進階:不可變類實例緩存模式與Integer.valueOf源碼剖析

     編輯:Java 程式設計入門

為什麼要實例緩存?

不可變類實例狀態不變,天然線程安全,適合共享。重用高頻實例可節省內存、減少GC壓力、提升性能。JDK 1.5在Integer、Short、Byte、Character、Boolean等包裝類引入靜態工廠方法valueOf()實現實例緩存。

Integer.valueOf核心邏輯(JDK 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);
}

默認緩存範圍-128 ~ 127(可通過-XX:AutoBoxCacheMax調整上限)。緩存實際為Integer[]數組,類加載時預創建。

代碼行為對比

Integer a = new Integer(10);
Integer b = new Integer(10);
Integer c = Integer.valueOf(10);
Integer d = Integer.valueOf(10);

System.out.println(a == b); // false:new每次創建新對象
System.out.println(a == c); // false:new vs 緩存
System.out.println(c == d); // true:同一緩存實例

僅創建3個對象:兩個new實例 + 一個緩存實例。最佳實踐:優先使用valueOf()獲取包裝類實例,除非明確需要獨立對象(極少見)。

自定義不可變類實現實例緩存:Name類示例

緩存設計需考慮:何時入緩存、何時清理失效引用、併發安全。簡單實現採用集合 + 軟引用(SoftReference):

public final class Name {
    private final String firstName;
    private final String lastName;
    
    // 緩存:Set>,JVM內存不足時自動回收
    private static final Set> cache = 
        Collections.synchronizedSet(new HashSet<>());
    
    private Name(String first, String last) {
        this.firstName = first;
        this.lastName = last;
    }
    
    public static Name valueOf(String first, String last) {
        // 1. 遍歷緩存查找匹配實例
        synchronized (cache) {
            for (SoftReference ref : cache) {
                Name n = ref.get();
                if (n != null && n.firstName.equals(first) && n.lastName.equals(last)) {
                    return n; // 命中緩存
                }
            }
        }
        // 2. 未命中:創建新實例,軟引用入緩存
        Name newInstance = new Name(first, last);
        cache.add(new SoftReference<>(newInstance));
        return newInstance;
    }
    
    // equals/hashCode基於firstName+lastName實現,省略...
}

關鍵點:

  • 類聲明final、字段final、無setter,保證不可變性。
  • 緩存用Set去重,SoftReference避免內存洩漏(JVM內存緊張時自動清理)。
  • valueOf同步遍歷+創建,簡單但高併發下有性能瓶頸。生產級可用ConcurrentHashMap + WeakReference + ReferenceQueue實現高效緩存(如Guava Interner)。
  • 提供new構造器供一次性實例使用,避免污染緩存。

擴展:JDK其他緩存類

總結

實例緩存是享元模式在不可變類上的經典應用。核心權衡:內存換CPU(減少分配/GC)、共享換線程安全。使用時遵循:優先valueOf()、理解緩存範圍、自定義類參考Soft/WeakReference防洩漏、注意併發性能。JDK源碼是最好的教材——IntegerCache僅百行代碼,卻蘊含極致工程智慧。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
類緩存範圍/策略備註
BooleanTRUE/FALSE兩個單例valueOf(boolean)直接返回常量
Byte-128 ~ 127 全範圍byte只有256值,全緩存
Short-128 ~ 127同Integer默認範圍
Character\u0000 ~ \u007F (0-127)基本ASCII範圍
Long-128 ~ 127JDK 8+引入
String字符串常量池編譯期常量、intern()手動入池