java克隆

本文详细介绍了Java中的克隆技术,包括其实现原理、应用场景及深浅克隆的区别。通过具体示例展示了如何实现Cloneable接口并重写clone方法以完成对象的复制,帮助读者深入理解克隆机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

what——克隆是什么?

克隆起源于生物学科,大致意思就是复制。在java中,克隆也是进行对象复制的操作。

how——怎样使用克隆?

实现克隆首先被克隆对象要实现Cloneable接口,同时要重写clone()方法,并且将方法权限设为public(需外不访问)!

why——为什么要克隆?

在开发中,多个地方共同引用、操作一个引用变量,但引用指向的物理存储堆是相同,操作之间会相互影响!因此,此时需要将操作引用对象进行克隆,避免多操作带来的相互影响!

下面就实现以下clone的使用:

public class CloneTest implements Cloneable {
	private String element1;
	public Object clone() {
		CloneTest cloneTest = null;
		try {
			cloneTest = (CloneTest)super.clone(); 
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return cloneTest;
	}
	public String getElement1() {
		return element1;
	}
	public void setElement1(String element1) {
		this.element1 = element1;
	}
	
}

在重写实现clone方法的时,首先应保证其修饰权限为public,由于我们需要在类外引用该方法。接下来实现了Cloneable接口,我们点开Cloneable接口,发现里面并没有任何方法,为啥呢?先往下看,clone方法调用了Object类的clone方法,Object中clone是个本地方法,并且抛出CloneNotSupportedException异常,此时就理解上面的Cloneable空接口的作用——标记克隆类!

克隆又有深克隆浅克隆或叫深拷贝浅拷贝,个人认为深浅克隆没啥分别,只是我们使用用途的不同而需要的clone对象不同而已,浅克隆:未递归将克隆类中的引用变量克隆(未实现克隆),反之则是深克隆。下面代码展示一下深浅克隆。

public class CloneTest implements Cloneable {
	private String element1;
	private CloneObj cloneObj ;
	public Object clone() {
		CloneTest cloneTest = null;
		try {
			cloneTest = (CloneTest)super.clone(); 
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return cloneTest;
	}
	public String getElement1() {
		return element1;
	}
	public void setElement1(String element1) {
		this.element1 = element1;
	}
	public CloneObj getCloneObj() {
		return cloneObj;
	}
	public void setCloneObj(CloneObj cloneObj) {
		this.cloneObj = cloneObj;
	}
	
}
public class CloneObj {
	private String elemOne;
	
	public String getElemOne() {
		return elemOne;
	}

	public void setElemOne(String elemOne) {
		this.elemOne = elemOne;
	}
	
}
上面代码为浅克隆,即在CloneTest类中引用的CloneObj也是克隆类,如果CloneObj未实现克隆,如下代码,则是深克隆。深浅克隆根据自己业务场景来处理自己的数据,个人觉得区不区分没意义!
public class CloneTest implements Cloneable {
	private String element1;
	private CloneObj cloneObj ;
	public Object clone() {
		CloneTest cloneTest = null;
		try {
			cloneTest = (CloneTest)super.clone(); 
			cloneTest.cloneObj = (CloneObj) cloneObj.clone();
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return cloneTest;
	}
	public String getElement1() {
		return element1;
	}
	public void setElement1(String element1) {
		this.element1 = element1;
	}
	public CloneObj getCloneObj() {
		return cloneObj;
	}
	public void setCloneObj(CloneObj cloneObj) {
		this.cloneObj = cloneObj;
	}
	
}

public class CloneObj implements Cloneable {
	private String elemOne;

	public Object clone() {
		CloneObj cloneObj = null;
		try {
			cloneObj = (CloneObj)super.clone(); 
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return cloneObj;
    }
	
	public String getElemOne() {
		return elemOne;
	}

	public void setElemOne(String elemOne) {
		this.elemOne = elemOne;
	}
	
}

总结:

克隆即是将对堆内的数据copy了一份,重新将指针分配其他变量,增大了内存的开销,因此不可滥用!!!



### Java 克隆对象的实现方式:浅克隆与深克隆 Java 中的对象克隆功能是通过 `Cloneable` 接口和 `Object` 类中的 `clone()` 方法来实现的。以下是关于克隆功能的详细说明: #### 1. 浅克隆克隆是指克隆出的新对象会复制原对象的所有基本数据类型字段,但对于引用类型的字段,新对象只会复制引用地址,而不是创建新的对象实例。这意味着原对象和克隆对象共享同一个引用类型的对象。 以下是一个浅克隆的示例代码[^4]: ```java class Student implements Cloneable { public String name; public int age; public Student(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Student{name='" + name + "', age=" + age + '}'; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } public class Test { public static void main(String[] args) throws CloneNotSupportedException { Student student = new Student("张三", 18); Student student1 = (Student) student.clone(); System.out.println(student); // 输出: Student{name='张三', age=18} System.out.println(student1); // 输出: Student{name='张三', age=18} } } ``` #### 2. 深克隆克隆是指不仅复制基本数据类型的字段,还对引用类型的字段也进行递归复制,确保原对象和克隆对象没有任何引用共享。 深克隆可以通过手动实现或使用序列化机制来完成。以下是一个手动实现深克隆的示例代码[^1]: ```java class Person implements Cloneable { String name; int age; int[] scores; public Person(String name, int age, int[] scores) { this.name = name; this.age = age; this.scores = scores; } @Override public Person clone() { try { Person cloned = (Person) super.clone(); cloned.scores = cloned.scores.clone(); // 深克隆数组 return cloned; } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; } } ``` 如果对象包含复杂的嵌套结构,可以递归调用每个子对象的 `clone()` 方法[^2]: ```java class Order implements Cloneable { private String orderId; private List<Item> items; @Override public Order clone() { try { Order cloned = (Order) super.clone(); cloned.items = new ArrayList<>(); for (Item item : this.items) { cloned.items.add(item.clone()); // 假设 Item 也实现了克隆 } return cloned; } catch (CloneNotSupportedException e) { throw new AssertionError(); } } } ``` #### 3. 使用序列化实现深克隆 另一种实现深克隆的方式是利用 Java 的序列化机制。这种方法适用于对象及其所有子对象都实现了 `Serializable` 接口的情况。 示例代码如下: ```java import java.io.*; public class DeepCopyUtil { public static <T> T deepClone(T obj) throws IOException, ClassNotFoundException { // 序列化 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(obj); // 反序列化 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); return (T) ois.readObject(); } } ``` #### 4. 注意事项 - **实现 Cloneable 接口**:必须让类实现 `Cloneable` 接口,否则调用 `clone()` 方法时会抛出 `CloneNotSupportedException` 异常[^1]。 - **覆盖 clone() 方法**:默认的 `clone()` 方法只执行浅克隆。如果需要深克隆,则需要手动处理引用类型的字段。 - **异常处理**:在实现 `clone()` 方法时,应捕获并处理 `CloneNotSupportedException` 异常。 - **特殊资源限制**:`clone()` 方法无法克隆线程、文件句柄等特殊资源。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值