天天看點

java中的三種拷貝方式

java中的三種拷貝方式

第一種 基本資料類型:
	八大基本資料類型:
	A a1 = a2
	我們需要了解的是這實際上複制的是引用:
	也就是說 a1 和 a2 指向的是同一個對象。是以,當 a1 變化的時候,a2 裡面的成員變量也會跟着變化。 

第二種 淺拷貝:(複制引用但不複制引用的對象) 
	建立一個新對象,然後将目前對象的非靜态字段複制到該新對象,如果字段是值類型的,那麼對該字段執行複制;
	如果該字段是引用類型的話,則複制引用但不複制引用的對象。是以,原始對象及其副本引用同一個對象。 
	Student stu1 = new Student();
	stu1.setNumber(12345);
	Student stu2 = stu1;
	
	System.out.println("學生1:" + stu1.getNumber());	// 學生1:12345
	System.out.println("學生2:" + stu2.getNumber());	// 學生2:12345
	
	但是如果:
	stu2.setNumber(54321);
	System.out.println("學生1:" + stu1.getNumber());	// 學生1:54321
	System.out.println("學生2:" + stu2.getNumber());	// 學生2:54321
	因為 stu1 和 stu2 指向記憶體堆中同一個對象
	解決方法:
		被複制的類需要實作Clonenable接口
		覆寫clone()方法,通路修飾符設為public。方法中調用super.clone()方法得到需要的複制對象,(native為本地方法)
	@Override
	public Object clone() {
		Student stu = null;
		try{
			stu = (Student)super.clone();
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return stu;
	}
	Student stu1 = new Student();
	stu1.setNumber(12345);
	Student stu2 = (Student)stu1.clone();
	System.out.println("學生1:" + stu1.getNumber());	// 學生1:12345
	System.out.println("學生2:" + stu2.getNumber());	// 學生2:12345
	stu2.setNumber(54321);
	System.out.println("學生1:" + stu1.getNumber());	// 學生1:12345
	System.out.println("學生2:" + stu2.getNumber());	// 學生2:54321
	
	但是又如果:
	Address addr = new Address();
	addr.setAdd("杭州市");
	Student stu1 = new Student();
	stu1.setNumber(123);
	stu1.setAddr(addr);
	Student stu2 = (Student)stu1.clone();
	System.out.println("學生1:" + stu1.getNumber() + ",位址:" + stu1.getAddr().getAdd());	// 學生1:123,位址:杭州市
	System.out.println("學生2:" + stu2.getNumber() + ",位址:" + stu2.getAddr().getAdd());	// 學生2:123,位址:杭州市
	addr.setAdd("西湖區");
	System.out.println("學生1:" + stu1.getNumber() + ",位址:" + stu1.getAddr().getAdd());	// 學生1:123,位址:西湖區
	System.out.println("學生2:" + stu2.getNumber() + ",位址:" + stu2.getAddr().getAdd());	// 學生2:123,位址:西湖區
	原因是淺複制隻是複制了addr變量的引用,将值複制後再将引用傳回給新對象,并沒有真正的開辟另一塊空間。
	淺拷貝:BeanUtils.copyProperties(executiveSummary, executiveSummaryOld);

第三種 深拷貝:(複制對象和其應用對象) 
	深拷貝不僅複制對象本身,而且複制對象包含的引用指向的所有對象。
	将Address類可複制化
	然後在student類中:
	@Override
	public Object clone() {
		Student stu = null;
		try{
			stu = (Student)super.clone();	//淺複制
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		stu.addr = (Address)addr.clone();	//深度複制
		return stu;
	}
	// 學生1:123,位址:杭州市
	// 學生2:123,位址:杭州市
	// 學生1:123,位址:西湖區
	// 學生2:123,位址:杭州市
	或者序列化實作:
	在 Java 語言裡深複制一個對象,常常可以先使對象實作 Serializable 接口,然後把對象(實際上隻是對象的一個拷貝)寫到一個流裡,再從流裡讀出來,便可以重建對象。 
           

繼續閱讀