一切從下面這段代碼開始程序員
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(); } }
執行後發現a
和b
引用對象的值確實交換了。code
可是在main()
的最後加上這段代碼,會發現輸出是c=2
!!對象
Integer c = 1; System.out.println("c=" + c);
查看字節碼能夠發現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。源碼
由此就能夠知道,由於a
和b
引用的是cache中的對象,swap()
後,cache中對象的值和其在數組中的下標已經不對應了,因此c
引用的對象的實際值是2。io
爲了不交換影響到Integer
的緩存,咱們必須使用new
來實例化a
和b
引用的對象。test
Java彷佛就是有意不讓程序員去修改對象內存的,只能改改引用的對象,像String
的替換、追加等操做,都是返回一個新實例化的對象,而不是在原對象的內存中修改。