先看下這段神奇的Java代碼:java
public static void main(String[] args) throws Exception { doSomethingMagic(); System.out.printf("2 + 2 = %d", 2 + 2); }
執行結果:2 + 2 = 5緩存
那麼doSomethingMagic到底作了什麼神奇的事情呢?先看代碼:編輯器
private static void doSomethingMagic() throws Exception { Class cache = Integer.class.getDeclaredClasses()[0]; Field c = cache.getDeclaredField("cache"); c.setAccessible(true); Integer[] array = (Integer[]) c.get(cache); array[132] = array[133]; }
因此這個例子其實包含了Java中整型類型Integer的一個知識點。spa
可能有的朋友對於doSomethingMagic裏面的代碼有點摸不着頭腦,讓咱們先查看上圖第17行 2 + 2反編譯出來的代碼:調試
編輯器將2+ 2的值先計算出來,等於4。最後System.out.println打印出來的值,其實是Integer.valueOf(4)的返回值。code
那麼咱們就查看JDK裏Integer.valueOf的實現:ip
上面的實現代碼,從830行到832行,邏輯很是清楚:若是valueOf的參數i在IntegerCache.low和IntegerCache.high之間,即[-128, 127]的閉區間,則直接從IntegerCache這個緩存區域裏返回。只有當輸入參數i不在[-128,127]區間內,才執行代碼832,基於輸入參數i建立一個新的Integer實例。rem
帶着這個理念,咱們再看doSomethingMagic就清楚多了。這個方法經過Java反射將上圖IntegerCache的成員cache設置成可訪問:setAccessible(true), 而後將IntegerCache的第132個元素的值用第133個元素的值覆蓋。get
咱們從Eclipse調試器裏發現,Integer cache裏第132個元素的值爲4,第133個元素的值爲5。原本Integer.valueOf方法,對於輸入4,從Integer cache裏返回第132個元素的值,即4。如今這個元素的值被第133個元素即5覆蓋了,因此最後獲得了 2 + 2 = 5。it
用一句話歸納這個場景: 2 + 2 = 4 = Integer.valueOf(4) = 5 ( 由於4在Integer cache裏對應的記錄已經被咱們的代碼顯式替換成了5)。
要獲取更多Jerry的原創技術文章,請關注公衆號"汪子熙"或者掃描下面二維碼: