Java语言的一个优点就是取消了指针的概念,但也导致了许多程序员在编程中常常忽略了对象与引用的区别,本文会试图澄清这一概念。并且由于Java不能通过简单的赋值来解决对象复制的问题,在开发过程中,也常常要要应用clone()方法来复制对象。本文会让你了解什么是影子clone与深度clone,认识它们的区别、优点及缺点。
看到这个标题,是不是有点困惑:Java语言明确说明取消了指针,因为指针往往是在带来方便的同时也是导致代码不安全的根源,同时也会使程序的变得非常复杂难以理解,滥用指针写成的代码不亚于使用早已臭名昭著的"GOTO"语句。Java放弃指针的概念绝对是极其明智的。但这只是在Java语言中没有明确的指针定义,实质上每一个new语句返回的都是一个指针的引用,只不过在大多时候Java中不用关心如何操作这个"指针",更不用象在操作C++的指针那样胆战心惊。唯一要多多关心的是在给函数传递对象的时候。如下例程:
package reference; class Obj{ String str = "init value"; public String toString(){ return str; } } 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); } } /* RUN RESULT Before call changeObj() method: init value After call changeObj() method: changed value ==================Print Primtive================= Before call changePri() method: 11 After call changePri() method: 11 * */
package reference; class PassObj { String str = "init value"; } public class ObjPassvalue { public static void main(String[] args) { PassObj objA = new PassObj(); PassObj objB = objA; objA.str = "changed in objA"; System.out.println("Print objB.str value: " + objB.str); } } /* RUN RESULT Print objB.str value: changed in objA */
package reference; import java.util.*; public class HashtableAdd{ public static void main(String[] args){ Hashtable ht = new Hashtable(); StringBuffer sb = new StringBuffer(); sb.append("abc,"); ht.put("1",sb); sb.append("def,"); ht.put("2",sb); sb.append("mno,"); 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()); } } }
class CloneClass implements Cloneable{ public int aInt; public Object clone(){ CloneClass o = null; try{ o = (CloneClass)super.clone(); }catch(CloneNotSupportedException e){ e.printStackTrace(); } return o; } }
package clone; class UnCloneA { private int i; public UnCloneA(int ii) { i = ii; } public void doublevalue() { i *= 2; } public String toString() { return Integer.toString(i); } } class CloneB implements Cloneable{ public int aInt; public UnCloneA unCA = new UnCloneA(111); public Object clone(){ CloneB o = null; try{ o = (CloneB)super.clone(); }catch(CloneNotSupportedException e){ e.printStackTrace(); } return o; } } public class CloneMain { public static void main(String[] a){ CloneB b1 = new CloneB(); b1.aInt = 11; System.out.println("before clone,b1.aInt = "+ b1.aInt); System.out.println("before clone,b1.unCA = "+ b1.unCA); CloneB b2 = (CloneB)b1.clone(); b2.aInt = 22; b2.unCA.doublevalue(); System.out.println("================================="); System.out.println("after clone,b1.aInt = "+ b1.aInt); System.out.println("after clone,b1.unCA = "+ b1.unCA); System.out.println("================================="); System.out.println("after clone,b2.aInt = "+ b2.aInt); System.out.println("after clone,b2.unCA = "+ b2.unCA); } } /** RUN RESULT: before clone,b1.aInt = 11 before clone,b1.unCA = 111 ================================= after clone,b1.aInt = 11 after clone,b1.unCA = 222 ================================= after clone,b2.aInt = 22 after clone,b2.unCA = 222 */
package clone.ext; class UnCloneA implements Cloneable{ private int i; public UnCloneA(int ii) { i = ii; } public void doublevalue() { i *= 2; } public String toString() { return Integer.toString(i); } public Object clone(){ UnCloneA o = null; try{ o = (UnCloneA)super.clone(); }catch(CloneNotSupportedException e){ e.printStackTrace(); } return o; } } class CloneB implements Cloneable{ public int aInt; public UnCloneA unCA = new UnCloneA(111); public Object clone(){ CloneB o = null; try{ o = (CloneB)super.clone(); }catch(CloneNotSupportedException e){ e.printStackTrace(); } o.unCA = (UnCloneA)unCA.clone(); return o; } } public class CloneMain { public static void main(String[] a){ CloneB b1 = new CloneB(); b1.aInt = 11; System.out.println("before clone,b1.aInt = "+ b1.aInt); System.out.println("before clone,b1.unCA = "+ b1.unCA); CloneB b2 = (CloneB)b1.clone(); b2.aInt = 22; b2.unCA.doublevalue(); System.out.println("================================="); System.out.println("after clone,b1.aInt = "+ b1.aInt); System.out.println("after clone,b1.unCA = "+ b1.unCA); System.out.println("================================="); System.out.println("after clone,b2.aInt = "+ b2.aInt); System.out.println("after clone,b2.unCA = "+ b2.unCA); } } /** RUN RESULT: before clone,b1.aInt = 11 before clone,b1.unCA = 111 ================================= after clone,b1.aInt = 11 after clone,b1.unCA = 111 ================================= after clone,b2.aInt = 22 after clone,b2.unCA = 222 */
package clone; class CloneC implements Cloneable{ public String str; public StringBuffer strBuff; public Object clone(){ CloneC o = null; try{ o = (CloneC)super.clone(); }catch(CloneNotSupportedException e){ e.printStackTrace(); } return o; } } public class StrClone { public static void main(String[] a){ CloneC c1 = new CloneC(); c1.str = new String("initializeStr"); c1.strBuff = new StringBuffer("initializeStrBuff"); System.out.println("before clone,c1.str = "+ c1.str); System.out.println("before clone,c1.strBuff = "+ c1.strBuff); CloneC c2 = (CloneC)c1.clone(); c2.str = c2.str.substring(0,5); c2.strBuff = c2.strBuff.append(" change strBuff clone"); System.out.println("================================="); System.out.println("after clone,c1.str = "+ c1.str); System.out.println("after clone,c1.strBuff = "+ c1.strBuff); System.out.println("================================="); System.out.println("after clone,c2.str = "+ c2.str); System.out.println("after clone,c2.strBuff = "+ c2.strBuff); } } /* RUN RESULT before clone,c1.str = initializeStr before clone,c1.strBuff = initializeStrBuff ================================= after clone,c1.str = initializeStr after clone,c1.strBuff = initializeStrBuff change strBuff clone ================================= after clone,c2.str = initi after clone,c2.strBuff = initializeStrBuff change strBuff clone * */
package clone; public class StrTest { public static void main(String[] args) { String str1 = "This is a test for immutable"; String str2 = str1.substring(0,8); System.out.println("print str1 : " + str1); System.out.println("print str2 : " + str2); } } /* RUN RESULT print str1 : This is a test for immutable print str2 : This is */