Java学习手册:clone方法(浅复制&深复制)

版权声明:本文为博主原创文章,未经博主允许不得转载,转载请务必注明出处: https://blog.csdn.net/MaybeForever/article/details/89226086

一、clone方法

在实际编程中,经常会遇到从某个已有的对象A创建出另外一个与A具有相同状态的对象B,并且对B的修改不会影响到A的状态。在Java语言中,仅仅通过简单的赋值操作显然无法达到这个目的,而Java提供了一个简单有效的clone()方法来满足这个需求。

Java中的所有类默认都继承自Object类,而Object类中提供了一个clone()方法。这个方法的作用是返回一个Object对象的复制。这个复制返回的是一个新的对象而不是一个引用。以下是使用clone()方法的步骤:
(1)实现clone的类首先需要继承Cloneable接口。Cloneable接口实质上是一个标识接口,没有任何接口方法。
(2)在类中重写Object类中的clone()方法。
(3)在clone方法中调用super.clone()。无论clone类的继承结构是什么,super.clone()都会直接或间接调用java.lang.Object类的clone()方法。
(4)把浅复制的引用指向原型对象新的克隆体。

package com.haobi;
/*
 * 使用clone()方法的步骤--浅复制
 */
class A implements Cloneable{//1、继承Cloneable接口
	private int a = 0;
	public int getInt() {
		return a;
	}
	public void setInt(int i) {
		a = i;
	}
	public void changeInt() {
		a = 1;
	}
	public Object clone() {//2、重写Object类的clone()方法
		Object o = null;
		try {
			o = (A)super.clone();//3、在clone()方法中调用super.clone()
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return o;
	}
}
public class TestClone {
	public static void main(String[] args) {
		A a = new A();
		A b = (A)a.clone();//4、把浅复制的引用指向原型对象的克隆体
		b.changeInt();
		System.out.println("a:"+a.getInt());
		System.out.println("b:"+b.getInt());
	}
}
//程序输出结果如下:
a:0
b:1

在C++语言中,当开发人员自定义复制构造函数时,会存在浅复制和深复制之分。Java语言在重载clone()方法时也存在同样的问题,当类中只有一些基本的数据类型时,采用上述方法就可以了,但是当类中包含了一些对象时,就需要用到深复制了,实现方法是在对对象调用clone()方法完成复制后,接着对对象中的非基本类型的属性也调用clone()方法完成深复制。示例如下:

package com.haobi;

import java.util.Date;
/*
 * 深复制 
 */
class AA implements Cloneable{
	
	private Date  birth = new Date();
	public Date getBirth() {
		return birth;
	}
	public void setBirth(Date birth) {
		this.birth = birth;
	}
	public void changeDate() {
		this.birth.setMonth(1);
	}
	public Object clone() {
		AA a = null;
		try {
			a = (AA)super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		//实现深复制
		a.birth = (Date)this.getBirth().clone();
		return a;
	}
}
public class TestClone1 {
	public static void main(String[] args) {
		AA a = new AA();
		AA b = (AA)a.clone();
		b.changeDate();
		System.out.println("a="+a.getBirth());
		System.out.println("b="+b.getBirth());
	}
}
//程序输出结果如下:
a=Fri Apr 12 15:53:04 CST 2019
b=Tue Feb 12 15:53:04 CST 2019

在编程时,首先检查类有无非基本类型(即对象)的数据成员。若没有,则返回super.clone()即可;若有,确保类中包含的所有非基本类型成员变量都实现了深复制。

Object o = super.clone();//先执行浅复制
o.attr = this,getAttr().clone();//然后对每一个对象attr执行以下语句
//最后返回o

需要注意的是,clone()方法的保护机制在Object中的clone()是被声明为protected的。以User类为例,通过声明为protected,就可以保证只有User类里面才能“克隆”User对象。

二、深复制和浅复制有什么区别?

浅复制(Shallow Clone):被复制对象的所有变量都含有与原来对象相同的值,而所有对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。

深复制(Deep Clone):被复制对象的所有变量都含有与原来对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制的新对象。而不再是原有的那些被引用的对象。换言之,深复制把复制的对象所引用的对象都复制了一遍。
以下例所示:

class Test{
	public int i;
	public StringBuffer s;
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/MaybeForever/article/details/89226086