1. 程式人生 > >【Java】連結串列中儲存物件的問題

【Java】連結串列中儲存物件的問題

  在刷《劍指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 1 
View 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”的地址,所以連結串列中的內容不變。

  更詳細的傳遞討論:值傳遞和引用傳遞討論