2009-07-18 41 views
8

考慮以下代碼:不一致的行爲

class test { 
    public static void main(String[] args) { 
     test inst_test = new test(); 
     int i1 = 2000; 
     int i2 = 2000; 
     int i3 = 2; 
     int i4 = 2; 
     Integer Ithree = new Integer(2); // 1 
     Integer Ifour = new Integer(2); // 2 
     System.out.println(Ithree == Ifour); 
     inst_test.method(i3 , i4); 
     inst_test.method(i1 , i2); 
    } 
    public void method(Integer i , Integer eye) { 
     System.out.println(i == eye); 
    } 
} 

它打印:

false 
true 
false 

我知道,第一false,==操作符只檢查兩個引用是否正在使用的相同對象,在這種情況下不是。

以下truefalse讓我撓了撓頭。 Java爲什麼會考慮i3i4等於i1i2不同?兩者都被封裝到整數,不應該評價爲false?這種不一致是否存在實際原因?

+2

我相信FindBugs會告訴你你的錯誤。 – 2009-07-18 23:18:43

回答

15

自動裝箱原語爲對象(如您的通話method用於使用小值的緩存從Java Language Specification section 5.1.7

如果被裝箱值p是真實的, 假,字節,炭在\ u0000的範圍 到\ u007f,或-128和127之間的int或短 號碼,然後讓 r1和r2是p中的任意兩個 裝箱轉換的結果。它始終是 的情況是R1 == r2。

緊隨其後的規範的討論部分也很有趣。值得注意的是一個JVM可以緩存值,如果它想 - 你不能肯定這樣做的結果:

Integer i1 = 129; 
Integer i2 = 129; 
boolean b = (i1 == i2); 
2

這是因爲拳擊使整數低於某個值(我認爲128)是指一些預構造的對象,以及更高的值到新的對象。

7

當自動裝箱時,緩存-128和127之間的整數,並返回相同的包裝對象。與\ u0000和\ u007F之間的布爾值和字符值相同。

這就是您大部分時間得到的結果,但它取決於JVM實現。

+3

我曾經認爲它也是JVM依賴的,但它實際上是在規範中。 – 2009-07-18 22:59:05

+2

(或者說,它是爲這些值指定的,但不適用於其他值。) – 2009-07-18 23:00:53

0

我猜測包裝會盡量減少整數對象的數量,並只創建一個代表2的對象,節省內存。

只記得不要在對象上使用==你永遠不會知道發生了什麼。

+0

是的,正如幾個人所說的,不要使用==,除非尋求具有「知道發生了什麼」支持的特定效果,並且一般使用: Boolean booLean = Boolean.valueOf(i.intValue()== eye.intValue()); System.out.println(booLean.toString()); – 2009-09-30 23:05:40

0

Integer類包含一些常用的實例的高速緩存。值的範圍一般從JVM變化到JVM(有時也可配置),但一般相關的代碼是一樣的東西:

public static Integer valueOf(int i) { 
    if(i >= -128 && i <= IntegerCache.high) 
     return IntegerCache.cache[i + 128]; 
    else 
     return new Integer(i); 
} 

(代碼太陽JDK 1.6)

這就像串實習,因爲它既節省了內存,又允許使用引用(例如,==代替等於

1

自動裝箱使用Integer.valueOf(ⅰ),不是新的整數(i)中,以構建Integer類的對象。

正如其他人所說的,valueOf()使用緩存,主要是爲了空間效率。

不要在引用類型上使用==,它幾乎總是一個錯誤。

0

自動裝箱使用一些緩存機制。通常你不應該依靠==,總是用equals來檢查平等。