2014-09-12 62 views
0

ArrayList和Integer都是對象數據類型,但爲什麼下面的代碼將這兩種方式區別對待? ar,br,a和b都是對象。 改變br改變br,但改變a沒有改變b爲什麼?是不是ArrayLists和Integers都是對象?通過使用=語句將對象分配給另一個對象只需執行淺拷貝FOR BOTH?或沒有?是什麼導致java以不同的方式處理ArrayLists和Integer這兩種對象類型?

import java.util.ArrayList; 
import java.util.Arrays; 

public class MyClass { 
    public static void main(String[] args) { 
     ArrayList <Integer> ar = new ArrayList<>(Arrays.asList(1,2,3)); 
     ArrayList<Integer> br = ar; 
     System.out.println(Arrays.toString(br.toArray()));// [1,2,3] 
     ar.remove(0);// lets change ar 
     // now lets see if br changed too 
     System.out.println(Arrays.toString(br.toArray()));// [2,3] (yes did) 

     Integer a= new Integer (5); 

     Integer b = a; 

     a = a+1;// lets change a and see if b changed too 

     System.out.println(b);// b is still 5 

     //So changing ar changed br too, but changing a did not change b why? Ist it both br and b are objects? 




    } 
} 
+1

線索是你寫了'a = ...'。 '='做什麼? – 2014-09-12 22:36:40

+0

這裏是一個閱讀所有聰明的人downvoted我的答案的主題:http://stackoverflow.com/questions/3131136/integers-caching-in-java – Lucas 2014-09-12 22:39:02

+1

@Lucas:你的答案是downvoted,因爲它是不正確的。值確實被緩存了,但這與這裏觀察到的行爲沒有關係。 – 2014-09-12 22:39:50

回答

4

這是因爲Integer對象實際上是boxed元。當您撥打Integer a= new Integer (5);時,您將創建一個新的整數。當你執行Integer b = a;時,那麼b指的是相同的 Integer實例。

當調用a = a+1;,會發生以下情況:

  1. 一個是裝箱成原始int具有值5。
  2. 加入一種該int的結果進行評價。
  3. 結果6被裝箱成新的Integer,其值爲6.未修改原始整數值5。

在列表中的情況下,你都分配和arbr指的java.util.ArrayList相同實例。當您通過arbr訪問該數組列表時,會看到對該數組列表的修改。

臨界點是a = a+1通過拆箱,評估和裝箱構建新的java.lang.Integer(),而ar.remove(0);會影響該列表而不創建新副本。

更多JLS讀數:

如果p int類型的值,然後裝箱轉換轉換峯值到類的參考r和鍵入整數,使得r.intValue() == p

+0

@OliCharlesworth謝謝,修復! – hexafraction 2014-09-12 22:44:17

-3

這只是問,今天早些時候,整數b是不變的,不會改變,但數組列表只是一個參考......

+3

這與不變性無關。 – 2014-09-12 22:37:02

1

您需要理解變量,引用值(以及對字段訪問和方法調用的解引用)和對象之間的區別。

變量只是一個值的持有者。

參考值是一個值,它被解釋爲一個對象的位置。

一個對象是......一個對象。它具有可訪問的字段和可調用的方法。

這裏

ArrayList <Integer> ar = new ArrayList<>(Arrays.asList(1,2,3)); 
ArrayList<Integer> br = ar; 

創建該存儲指向與new ArrayList<>(..)創建的單一實例的單一參考值的兩個變量。所以這兩個變量都引用同一個對象。

當通過使用一個方法調用表達式

ar.remove(..); 

JVM使用所述參考值來尋找對象和調用其方法調用的方法。這是br引用的同一個對象。所以,當你做

br.toArray() 

你仍然訪問相同的對象。

這裏

Integer a = new Integer (5); 
Integer b = a; 

創建兩個變量都引用同一個對象。

那麼你就

a = a+1;// lets change a and see if b changed too 

其中分配(=)新的基準值到可變a。所以現在a引用與b不同的對象。

0

所以:

ArrayList <Integer> ar = new ArrayList<>(Arrays.asList(1,2,3)); 
ArrayList<Integer> br = ar; 
System.out.println(Arrays.toString(br.toArray()));// [1,2,3] 

arbr是相同的實例

ar.remove(0);// lets change ar 
// now lets see if br changed too 
System.out.println(Arrays.toString(br.toArray()));// [2,3] (yes did) 

內容ar改變。由於ar == br,變化可見br

Integer a = new Integer (5); 
Integer b = a; 

a是一個新對象,並再次b被指定爲同一個實例

a = a+1; // lets change a and see if b changed too 
System.out.println(b); // b is still 5 

a參考被改變。現在a指向一個新創建的對象。 b仍然指向第一個創建的對象。

相關問題