一切从下面这段代码开始程序员
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
的替换、追加等操做,都是返回一个新实例化的对象,而不是在原对象的内存中修改。