2013-07-05 51 views
7

我在比較2段代碼。首先Integer i = 3 vs Integer i = new Integer(3)

Integer i=3; 
Integer j=3; 
if(i==j) 
    System.out.println("i==j"); //prints i==j    

其次,

Integer i=3; 
Integer j=new Integer(3); 
if(i==j) 
    System.out.println("i==j"); // does not print 

我都懷疑,在第一個片段,爲什麼i==j正在打印?不應該引用不同?

+0

與引用,新,對象,比較內存地址#Idk#CIS20 ... Somthing –

+0

'=='比較引用不值,當您分配。在第一種情況下,'i','j'指向內存中的相同整數。在第二種情況下使用new,則創建兩個具有相同值3的對象整數的新實例。 –

+0

這不是鏈接問題的副本。注意,由於錯誤的前提「新Integer(1)== new Integer(1)',這個問題被視爲」不是真正的問題「,這是不正確的。 –

回答

0

因爲在第二個代碼中你的第一個整數是自動裝箱,而第二個整數不是。

這意味着正在創建一個新的Integer實例。這兩個對象實例是不同的。等式檢查將在那裏返回false,因爲這兩個實例實際上是不同的內存片段。

+1

不,這是在這兩種情況下都使用自動裝箱的第一塊*代碼;第二個僅用於第一個值。 –

+0

我指的是第一個整數,而不是第二個整數。 –

+0

那是非常不清楚的。從這個答案中*仍然不清楚爲什麼第一段代碼打印出「i == j」,因爲你沒有解釋關於拳擊緩存本質的任何內容。 –

1

不是,他們不應該這樣做,因爲java可以在自動裝箱時使用預先編制的Integer對象進行小數字編輯。

5

Java池在-128到127之間整數,因此兩個引用都是相同的。

Integer i=3; 
Integer j=3; 

這導致自動裝箱和3被轉換爲整數3。因此,對於i的參考整數對象是在常量池,現在當你J = 3,相同的附圖作爲我的是分配給j。

而下面的代碼:

Integer j=new Integer(3); 

總是導致一個新的整數創作,堆。這不是合併的。因此你看到兩個引用都指向不同的對象。其結果爲

Integer i=3; 
Integer j=new Integer(3); 
if(i==j) 
    System.out.println("i==j"); // **does not print** 
+0

...在第一種情況下。 –

0

解釋器/ JIT優化器可以將所有3放在同一個框中。但是如果你強迫一個「新」,那麼你會得到另一個地址。

嘗試

j=8; // after initialization of i and j 

然後看到第一個版本J的地址改變。

19

這是關於如何拳擊的作品。從JLS section 5.1.7

如果被裝箱值p爲真,假,字節,或在範圍\ u0000的一個char到\ u007f,或-128和127之間int或短號碼(含) ,那麼讓r1和r2是p的任何兩次裝箱轉換的結果。 r1 == r2總是如此。

基本上,Java實現必須緩存盒裝的表示,適當的小值,並可能緩存更多。 ==運算符只是比較引用,所以它專門檢測兩個變量是否引用同一個對象。在第二個代碼片段中,它們肯定不會,因爲new Integer(3)肯定不是與之前創建的任何一個引用相同的引用......它總是會創建一個新對象。

由於上述規則,該代碼必須給予同樣的結果:

Integer x = 127; 
Integer y = 127; 
System.out.println(x == y); // Guarantee to print true 

儘管這可能會有兩種方式:

Integer x = 128; 
Integer y = 128; 
System.out.println(x == y); // Might print true, might print false 
+0

你應該解釋==比較。 –

+0

這是爲什麼downvoted? – jason

+2

@威廉莫里森:不同意。 OP顯然已經知道'=='是引用相等。問題在於他錯誤地期望引用不同(也就是說,這裏缺少的概念是對某些原語的「實習」,而不是對'=='進行修飾)。 – jason

0

類似方式字符串時,使用自動裝箱,例如在

Integer i = 3; 
Integer j = 3; 

Java can dra w來自預製物品池。在j的情況下,已經有一個Integer實例表示池中的值爲3,所以它從中抽取。因此,ij指向相同的東西,因此i == j

在你的第二個例子中,你明確實例化一個新的Integer對象j,所以ij指向不同的對象,從而i != j

2

我懷疑在第一個代碼段中爲什麼i == j正在打印? 不應該引用不同嗎?

因爲,

Integer i=3; 
    Integer j=3; 

在內部使用Integer#valueOf()執行autoBoxing。並且oracle doc說的方法是valueOf()

返回一個Integer實例,表示指定的int值。如果不需要新的Integer實例,則此方法通常應該優先於構造函數Integer(int)使用 ,因爲此方法爲 可能通過 高速緩存頻繁請求的值而產生顯着更好的空間和時間性能。 此方法將始終緩存 值在-128至127(含)範圍內,並可緩存其他值 以外的此範圍。

由於值3因此緩存,這兩個變量ij正在引用相同的對象。所以,i==j正在返回trueInteger#valueOf()使用flyweight pattern

2
Integer i=3; 
Integer j=3; 
if(i==j)System.out.println("i==j"); 

這裏,3被自動盒裝因此ij指向同一Integer

Integer i=3; 
Integer j=new Integer(3); 
if(i==j)System.out.println("i==j"); // does not print 

這裏,i點自動裝箱Integerj指向一個新的Integer因此存在引用失敗等號==操作測試。

但是,這裏有更多的想法。

Integer i=300; 
Integer j=300; 
if(i!=j)System.out.println("i!=j"); // prints i!=j 

爲什麼?因爲,自動裝箱僅在-128至127之間共享Integer實例。但是,這種行爲在不同的Java實現中可能會有所不同。

+0

'Integer'的池不是由JVM完成的,它完全由'Integer'完成,參見'Integer'的源代碼 –

+0

@SteveKuo我剛剛檢查過'Integer.valueOf()',並且是範圍IntegerCache.high「(127)之間的整數」Integer「,我糾正了我的答案,謝謝。 –

0

在下面的代碼的片:

Integer i=3; 
Integer j=3; 
if(i==j) 
    System.out.println("i==j"); 

在這裏,「==」相互比較參考而不是值。 因此,Integer i和j都指向內存中的相同引用。

,而在下面的代碼的片:

Integer i=3; 
Integer j=new Integer(3); 
if(i==j) 
    System.out.println("i==j"); 

的參考這兩個值被改變,因爲「J」在存儲器中新創建的整數的對象/參考而「I」是單指的值。

因此,第一個代碼的輸出是「i == j」,第二個代碼沒有任何輸出。

希望這會有所幫助。