java中的克隆,就是要複製對象,但爲什麼要用克隆呢?我們直接把對象賦值給其它同類型的實例不就行了嗎?這就要從java的值傳遞和引用傳遞說起了。
package dcr.study.test.pointer; public class Obj { String str = "init value"; public String toString() { return str; } }
測試值傳遞和引用傳遞的代碼如下:(注:註釋中說明了代碼的作用)
package dcr.study.test.pointer;
import java.util.Enumeration;
import java.util.Hashtable;
/*
*
* */
public class ObjRef {
Obj aObj = new Obj();
int aInt = 11;
public void changeObj(Obj inObj) {
inObj.str = "changed value";
}
public void changePri(int inInt) {
inInt = 22;
}
public static void main(String[] args) {
ObjRef oRef = new ObjRef();
System.out.println("Before call changeObj() method: " + oRef.aObj);
oRef.changeObj(oRef.aObj);
System.out.println("After call changeObj() method: " + oRef.aObj);
System.out.println("==================Print Primtive=================");
System.out.println("Before call changePri() method: " + oRef.aInt);
oRef.changePri(oRef.aInt);
System.out.println("After call changePri() method: " + oRef.aInt);
/*
* 運行結果如下 Before call changeObj() method: init value After call changeObj()
* method: changed value ==================Print Primtive=================
* Before call changePri() method: 11 After call changePri() method: 11
*
* 方法changeObj(Obj inObj);和方法changePri(int inInt);都是去改變傳入的參數值,
* 不同的是changeObj(Obj inObj);方法傳過的是一個對象,而changePri(int inInt);
* 方法傳入的卻是java的基本類型int,雖然兩個方法做了類似的事,但是結果卻不一樣,傳對象
* 的方法值被改掉了,但是傳java基本類型的方法,值還是原來的值。
* 原因是java參數的傳遞分爲兩種,值傳遞和引用傳遞(不光是java其它語言也一樣)。
* 值傳遞:在java中以 基本類型 和 基本類型的包裝類
* 做爲參數時,都是值傳遞。 引用傳遞:以對象做爲參數時爲引用傳遞。
*
*/
System.out.println("==================引用傳遞=================");
// 除了在函數傳值的時候是"引用傳遞",在任何用"="向對象變量賦值的時候都是"引用傳遞"
ObjRef oRefA = new ObjRef();
ObjRef oRefB = oRefA;
oRefA.aObj.str = "改變oRefA的Obj實例的值";
System.out.println("Print objB.str value: " + oRefB.aObj.str);
// 此處我們只改變了oRefA 的 Obj實例的str的值,但是oRefB的Obj實例的str的值同時也變了。
// 說明了在使用 “=” 號向對象變量賦值的時候,也是使用了“引用傳遞“。
System.out.println("=============引用傳遞導致的麻煩=============");
// 下面是關於HashTable的一個例子,HashTable真的能存儲對象嗎?
Hashtable ht = new Hashtable();
StringBuilder sb = new StringBuilder();
sb.append("abc");
ht.put(1, sb);
sb.append("def");
ht.put(2, sb);
sb.append("ghi");
ht.put(3, sb);
sb.append("xyz");
ht.put(4, sb);
int numObj = 0;
Enumeration it = ht.elements();
while (it.hasMoreElements()) {
System.out.print("get StringBufffer " + (++numObj)
+ " from Hashtable: ");
System.out.println(it.nextElement());
}
/*
運行結果如下:
=============引用傳遞導致的麻煩=============
get StringBufffer 1 from Hashtable: abcdefghixyz
get StringBufffer 2 from Hashtable: abcdefghixyz
get StringBufffer 3 from Hashtable: abcdefghixyz
get StringBufffer 4 from Hashtable: abcdefghixyz
而不是我們期望的
=============引用傳遞導致的麻煩=============
get StringBufffer 1 from Hashtable: abcdefghixyz
get StringBufffer 2 from Hashtable: abcdefghi
get StringBufffer 3 from Hashtable: abcdef
get StringBufffer 4 from Hashtable: abc
原因就是引用的傳遞
如果在向Hashtable put的時候在 sb的後面加上toString()方法,則可以得到
我們想要的結果。如:ht.put(1,sb.toString());因爲java中基本類型和
基本類型的包裝類都是值傳遞。
*/
}
}