這是一個挺有意思的討論話題

這是一個挺有意思的討論話題。

如果你運行下面的代碼:

<code>

Integer

 a = 

1000

, b = 

1000

;       

System

.out.

println

(a == b);     

Integer

 

c

 = 

100

, d = 

100

;       

System

.out.

println

(

c

 == d);/<code>

你會得到

<code>

false

true

/<code>

基本知識:我們知道,如果兩個引用指向同一個對象,用==表示它們是相等的。如果兩個引用指向不同的對象,用==表示它們是不相等的,即使它們的內容相同。

因此,後面一條語句也應該是false 。

這就是它有趣的地方了。如果你看去看 Integer.java 類,你會發現有一個內部私有類,IntegerCache.java,它緩存了從-128到127之間的所有的整數對象。

所以事情就成了,所有的小整數在內部緩存,然後當我們聲明類似——

<code>

Integer

 c = 

100

;/<code>

的時候,它實際上在內部做的是:

<code>

Integer

 i = Integer.valueOf(

100

);/<code>

現在,如果我們去看valueOf()方法,我們可以看到

<code>

public

 

static

 Integer 

valueOf

(

int

 i) {       

if

 (i >= IntegerCache.low && i           

return

 IntegerCache.cache[i + (-IntegerCache.low)];       

return

 

new

 Integer(i);     }/<code>

如果值的範圍在-128到127之間,它就從高速緩存返回實例。

所以…

<code>

Integer

 

c

 

=

 

100

,

 

d

 

=

 

100

;

/<code>

指向了同一個對象。

這就是為什麼我們寫

<code>

System

.out.

println

(

c

 == d);/<code>

我們可以得到true。

現在你可能會問,為什麼這裡需要緩存?

合乎邏輯的理由是,在此範圍內的“小”整數使用率比大整數要高,因此,使用相同的底層對象是有價值的,可以減少潛在的內存佔用。

然而,通過反射API你會誤用此功能。

運行下面的代碼,享受它的魅力吧

<code>

public

 static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {       Class cache = Integer

.

class

.

getDeclaredClasses

()[

0

];        Field myCache = cache.getDeclaredField(

"cache"

);        myCache.setAccessible(

true

);       Integer[] newCache = (Integer[]) myCache.

get

(cache);        newCache[

132

] = newCache[

133

];        int a = 

2

;       int b = a + a;       System.

out

.printf(

"%d + %d = %d"

, a, a, b);      }/<code>


分享到:


相關文章: