更新:html
在一次搜索「變量聲明在循環體內仍是循環體外」問題時,遇見了一個這樣的代碼,與本文相似,代碼以下:java
Document [] old ......//這是數據源 EntityDocument[] newArray = new EntityDocument[old.length];//自定義的類,爲了把Document裏數據保留下來避免Document被關聯對象關閉而致使沒法取出數據。 EntityDocument d = new EntityDocument(); for(int i=0;i<old.length;i++){ d.content = old[i].getContent(); d.key = old[i].getKey(); d...................... newArray[i] = d;//如此對象重用..... }
上面的代碼最終結果會致使newArray數組中的每一個元素都等於最後一個元素,緣由就是每次向newArray中存儲對象時,沒有新建一個對象進行儲存,從而致使錯誤。數組
上面代碼只須要將第3行的 EntityDocument d = new EntityDocument(); 放入循環體內便可實現正常功能。ide
這種錯誤隱藏得比較深,因此要好好記住。spa
原文code
在刷《劍指OFFER》的時候,本身犯了一個錯誤,發現:在鏈表中存儲一個對象時,若是該對象是不斷變化的,則應該建立一個新的對象複製該對象的內容(而不是指向同一個對象),將這個新的對象存儲到鏈表中。若是直接存儲該對象的話,鏈表中的對象也會不斷變化。基本數據類型和String則沒有這種問題。htm
其實這歸根結底是一個傳值和傳引用的問題:對象
1.若是存儲到鏈表中的是對象,則存儲的是引用(地址),因此該地址上的內容變化時,會引發對象的變化。blog
2.若是存到鏈表中的是基本數據類型或者String,存儲的就是該數值,不會再發生變化了。(其實String是對象,存儲的是引用,後面討論)。get
舉個例子:
import java.util.ArrayList; public class Test { public static class Person { int age=1; } public static void main(String[] args) { //=======ArrayList存儲String或者基礎數據類型========= ArrayList<String> list = new ArrayList<>(); String aString="abc"; list.add(aString); System.out.println("before:"+list.toString()); aString="123"; System.out.println("after:"+list.toString()); //========ArrayList存儲對象======= ArrayList<Person> pList = new ArrayList<>(); Person a = new Person(); Person b = new Person(); b = a; Person c = new Person(); c.age=a.age; pList.add(a); pList.add(b); pList.add(c); System.out.print("before:"); for (Person person : pList) { System.out.print(person.age+" "); //a,b,c的age此時都是1 } System.out.println(); a.age=2; System.out.print("after:"); for (Person person : pList) { System.out.print(person.age+" "); //輸出:2,2,1 } //關鍵緣由:b是和a指向同一個對象,c不是同一個對象 } }
before:[abc] after:[abc] before:1 1 1 after:2 2 1
上面的代碼能夠知道,存儲Person這個對象時(存儲的是地址),b和a實際上是同一個地址,因此a指向的對象改變,會引發鏈表中的前兩個結點(地址相同)改變,而若是要使存進鏈表的person存儲的是a存儲時的狀態,只能新建一個對象c,令c的內容等於a,纔在後面不會發生變化(由於該地址指向的內容沒有再發生改變了)。
關於String的討論:其實String也是對象,存儲的其實也是引用(地址),但爲何上面代碼中before和after輸出的內容都是「abc」呢?其實在aString="123";時,至關於aString=new String("123"),即aString指向了另外一個對象,aString存儲的地址變成了「123」的地址,但鏈表中存儲的仍是「abc」的地址,因此鏈表中的內容不變。
更詳細的傳遞討論:值傳遞和引用傳遞討論