【Java】連結串列中儲存物件的問題
阿新 • • 發佈:2018-11-09
在刷《劍指OFFER》的時候,自己犯了一個錯誤,發現:在連結串列中儲存一個物件時,如果該物件是不斷變化的,則應該建立一個新的物件複製該物件的內容(而不是指向同一個物件),將這個新的物件儲存到連結串列中。如果直接儲存該物件的話,連結串列中的物件也會不斷變化。基本資料型別和String則沒有這種問題。
其實這歸根結底是一個傳值和傳引用的問題:
1.如果儲存到連結串列中的是物件,則儲存的是引用(地址),所以該地址上的內容變化時,會引起物件的變化。
2.如果存到連結串列中的是基本資料型別或者String,儲存的就是該數值,不會再發生變化了。(其實String是物件,儲存的是引用,後面討論)。
舉個例子:
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 1View Code
上面的程式碼可以知道,儲存Person這個物件時(儲存的是地址),b和a其實是同一個地址,所以a指向的物件改變,會引起連結串列中的前兩個結點(地址相同)改變,而如果要使存進連結串列的person儲存的是a儲存時的狀態,只能新建一個物件c,令c的內容等於a,才在後面不會發生變化(因為該地址指向的內容沒有再發生改變了)。
關於String的討論:其實String也是物件,儲存的其實也是引用(地址),但為什麼上面程式碼中before和after輸出的內容都是“abc”呢?其實在aString="123";時,相當於aString=new String("123"),即aString指向了另一個物件,aString儲存的地址變成了“123”的地址,但連結串列中儲存的還是“abc”的地址,所以連結串列中的內容不變。
更詳細的傳遞討論:值傳遞和引用傳遞討論