Java學習點滴——Integer緩存

前言

一切從下面這段代碼開始程序員

public static void test(String[] agrs){
    Integer a = 1;
    Integer b = 2;
    System.out.println("a=" + a + ", b=" + b);
    swap( a, b );
    System.out.println("a=" + a + ", b=" + b);
}

public static void swap( Integer a, Integer b ){
    // 實現它
}

過程

由於Java中的方法只有值傳遞,因此沒法使用下面的方式來完成交換。數組

public static void swap( Integer a, Integer b ){
    Integer tmp = a;
    a = b;
    b = tmp;
}

由於Integer沒有提供直接修改值的方法,因此能想到的就是用反射機制去修改Integer對象持有的值。因而就有了下面的代碼緩存

public static void swap( Integer a, Integer b ){
    try {
        Integer tmp = new Integer(a);
        Field fieldA = a.getClass().getDeclaredField("value");
        fieldA.setAccessible(true);
        fieldA.set(a, b);

        Field fieldB = b.getClass().getDeclaredField("value");
        fieldB.setAccessible(true);
        fieldB.set(b, tmp);
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } 
}

執行後發現ab引用對象的值確實交換了。code

可是在main()的最後加上這段代碼,會發現輸出是c=2!!對象

Integer c = 1;
System.out.println("c=" + c);

Integer緩存

查看字節碼能夠發現Integer a = 1;實際是經過Integer.valueOf()獲取的Integer對象。
Integer.valueOf()源碼以下內存

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

咱們發現當i在[IntegerCache.low,IntegerCache.high]區間內時,老是返回cache中的對象引用。get

low不可配置,默認爲-128;high可配置,默認爲127。源碼

由此就能夠知道,由於ab引用的是cache中的對象,swap()後,cache中對象的值和其在數組中的下標已經不對應了,因此c引用的對象的實際值是2。io

爲了不交換影響到Integer的緩存,咱們必須使用new來實例化ab引用的對象。test

結語

Java彷佛就是有意不讓程序員去修改對象內存的,只能改改引用的對象,像String的替換、追加等操做,都是返回一個新實例化的對象,而不是在原對象的內存中修改。

相關文章
相關標籤/搜索