import java.lang.reflect.Field; public class MainClass { public static void main(String[] args) { Integer a = 128; Integer b = -129; swarp(a,b); System.out.println(a); System.out.println(b); try { System.out.println("________________________________________________"); swarp1(a,b); System.out.println(a); System.out.println(b); System.out.println("--------------------------------------------------"); Integer c = 128; System.out.println(c); Integer d = new Integer(128); System.out.println("--------------------------------------------------"); swarp2(a,d); System.out.println(a); System.out.println(d); } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void swarp(Integer a, Integer b){ Integer temp = a; a = b; b = temp; } public static void swarp1(Integer a, Integer b) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{ Field field = a.getClass().getDeclaredField("value"); field.setAccessible(true); Integer a1 = a; field.set(a, b); field.set(b, a1); field.setAccessible(false); } public static void swarp2(Integer a, Integer b) { Field field; try { field = a.getClass().getDeclaredField("value"); field.setAccessible(true); int a1 = new Integer(a); field.set(a, b); field.set(b, a1); field.setAccessible(false); } catch (NoSuchFieldException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
java 8
Integer 內部類
private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() {} }
內部類預初始化從-128~127的Integer實例,每個具體實例的下標為i + (-IntegerCache.low),比如-128下標為-128-(-128)=0,再看一下自動裝箱的函數valueOf
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
到這里我們上面的類的結果已經很明顯
一、將在main函數內,將a,b,c,d 分別賦值為128,-129,128,128
輸出結果為:
128
-129
________________________________________________
-129
128
--------------------------------------------------
128
--------------------------------------------------
128
-129
二、將main函數內的a,b,c,d 分別賦值為127,-128,127,127
輸出結果為:
127
-128
________________________________________________
-128
-128
--------------------------------------------------
-128
--------------------------------------------------
127
-128
如果讀到這里還不知道為什么會有這樣的結果,那么請繼續看
1、java 的傳參都是傳值,函數接收到的形參都是指向實例引用的副本,第一個函數(swap)在內部的操作都是對副本的操作,所以不管值是多少,兩個值得交換都失敗
2、當ab的值在-128~127范圍內時,第二個函數內,雖然給a做了備份,但是已經利用反射,將具體的在緩存內相應下標的Integer的value值改變,在b值賦值時,調用valueOf,指向該實例,所以返回的結果是ab值相等;而第三個函數為什么會交換成功呢?因為d是new出來的值,並沒有走valueOf自動裝箱,是一個在緩存之外的實例
3、當ab值在-128~127范圍外時,ab都是new的新實例,固可以交換成功