【Java】鏈表中存儲對象的問題

更新: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 
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」的地址,因此鏈表中的內容不變。

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

相關文章
相關標籤/搜索