java clone 对象_java对象的clone

克隆的目的:快速创建一个已有对象的副本。

克隆的步骤:

创建一个对象

将原有对象的数据导入到新创建的数据中

clone方法首先会判对象是否实现了Cloneable接口,若无则抛出CloneNotSupportedException, 最后会调用internalClone. intervalClone是一个native方法,一般来说native方法的执行效率高于非native方法。

源码:

86c0dad57346b27eb3cfd307c4c45e59.png

当某个类要复写clone方法时,要继承Cloneable接口。通常的克隆对象都是通过super.clone()方法来克隆对象。

2.浅克隆(shadow clone)

克隆就是复制一个对象的复本.若只需要复制对象的字段值(对于基本数据类型,如:int,long,float等,则复制值;对于复合数据类型仅复制该字段值,如数组变量则复制地址,对于对象变量则复制对象的reference。

实现Cloneable接口的类都具备被拷贝的能力,拷贝在内存中进行,比new生成对象性能明显提升;

clone方法是Object类的protected方法,也就是在用户编写的代码中不能直接调用。为此必须重写定义clone方法,并声明为public,

Cloneable接口的出现与接口正常使用没有关系,是一个空接口,它只是一个标记表示一个对象需要克隆,如果一个对象需要克隆,而没有实现Cloneable接口,就会产生一个CloneNotSupportedException异常

Clone()方法存在与Object对象中,但是其不会将对象的全部属性都拷贝,而是有选择的拷贝基本类型:对象:如果变量是一个实例对象,只拷贝地址引用;

String字符串:拷贝地址引用,但是修改时,会从字符串池中重新生成新的字符串,原来的保持不变;对于Clone实现对象的拷贝:需要新建大量的对象,工程量大可以使用序列化来实现对象的拷贝

需要clone的对象:

packagecom.gzu.pyu.thinking.in.java.practice0211;importjava.io.Serializable;public class Student implementsCloneable ,Serializable {publicString name;public intage;publicAddress address;publicStudent() {

}public Student(String name, intage, Address address) {this.name =name;this.age =age;this.address =address;

}publicAddress getAddress() {returnaddress;

}public voidsetAddress(Address address) {this.address =address;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}

@OverridepublicObject clone() {

Student student=null;try{//淺拷貝

student= (Student)super.clone();

}catch(CloneNotSupportedException e) {return newStudent();

}//支持深度克隆

student.address=address.clone();returnstudent;

}

@OverridepublicString toString() {final StringBuffer sb = new StringBuffer("Student{");

sb.append("name='").append(name).append('\'');

sb.append(", age=").append(age);

sb.append(", address=").append(address);

sb.append('}');returnsb.toString();

}

}class Address implementsCloneable,Serializable{

String city;

String town;publicAddress() {

}publicAddress(String city, String town) {this.city =city;this.town =town;

}publicString getCity() {returncity;

}public voidsetCity(String city) {this.city =city;

}publicString getTown() {returntown;

}public voidsetTown(String town) {this.town =town;

}

@OverridepublicAddress clone() {

Address address=null;try{

address= (Address) super.clone();

}catch(CloneNotSupportedException e) {return newAddress();

}returnaddress;

}

@OverridepublicString toString() {final StringBuffer sb = new StringBuffer("Address{");

sb.append("city='").append(city).append('\'');

sb.append(", town='").append(town).append('\'');

sb.append('}');returnsb.toString();

}

}

测试方法如下:

packagecom.gzu.pyu.thinking.in.java.practice0211;importcom.gzu.pyu.thinking.in.java.utils.CloneUtils;public classTestMain {public static voidmain(String ... args){

Address address=new Address("ShengZheng","LongGang");//将address指向的区域赋值给addressNew,使得addressNew和address同时指向了同一个区域

Address addressNew=address;//address指向的内容改变了,addressNew指向的内容也跟着改变

System.out.println(address==addressNew);//true

address.setCity("GuiYang");

System.out.println(address);//Address{city='GuiYang', town='LongGang'}

System.out.println(addressNew);//Address{city='GuiYang', town='LongGang'}//address進行克隆,將address進行了复制了,产生了一个新的对象

Address addressClone =address.clone();

System.out.println(address==addressClone);//false

address.setTown("HuaXi");

System.out.println(address);//Address{city='GuiYang', town='HuaXi'}

System.out.println(addressClone);//Address{city='GuiYang', town='LongGang'}//在内存中通过字节流的拷贝是比较容易的,把木对象写入到一个字节流中,再从字节流中读出来

Address addr =CloneUtils.clone(address);

System.out.println(address==addr);//false

addr.setCity("PanZhou");

System.out.println(address);//Address{city='GuiYang', town='HuaXi'}

System.out.println(addr);//Address{city='PanZhou', town='HuaXi'}

}

}

二、使用序列化来实现对象的拷贝

在内存中通过字节流的拷贝是比较容易的,把木对象写入到一个字节流中,再从字节流中毒出来,这样可以创建一个新的对象,且新对象与木对象不存在引用共享的问题,实现的对象的深拷贝

packagecom.gzu.pyu.thinking.in.java.utils;import java.io.*;/*** 在内存中通过字节流的拷贝是比较容易的,把木对象写入到一个字节流中,再从字节流中读出来,

* 这样可以创建一个新的对象,且新对象与木对象不存在引用共享的问题,实现的对象的深拷贝*/

public classCloneUtils {

@SuppressWarnings("unchecked")public static T clone(T obj){

T cloneObj= null;//写入字节流

try{

ByteArrayOutputStream out= newByteArrayOutputStream();

ObjectOutputStream obs= newObjectOutputStream(out);

obs.writeObject(obj);

obs.close();//分配内存,写入原始对象,生成新对象

ByteArrayInputStream ios = newByteArrayInputStream(out.toByteArray());

ObjectInputStream ois= newObjectInputStream(ios);//返回生成的新对象

cloneObj =(T) ois.readObject();

ois.close();

}catch(IOException e){

e.printStackTrace();

}catch(ClassNotFoundException e) {

e.printStackTrace();

}returncloneObj;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中的clone()方法是Object类中定义的方法,它用于创建并返回当前对象的一个副本。这个副本就是一个新的对象,它与原始对象具有相同的属性和方法。通常情况下,我们需要在一个类中实现clone()方法来支持对象的克隆。 克隆对象是在Java中处理对象的一种常见方式。通过克隆,我们可以在不修改原始对象的情况下创建该对象的一个副本。这在某些情况下是非常有用的,例如在多线程环境下,我们需要多个线程同时访问同一个对象,但是又不希望它们之间相互干扰。 在Java中,要使用clone()方法来实现对象的克隆,我们需要满足两个条件: 1. 实现Cloneable接口:这个接口是一个标记接口,它没有任何方法,只是用来标记一个类可以被克隆。 2. 重写clone()方法:这个方法是Object类中的一个protected方法,需要在我们的类中进行重写。在重写这个方法时,我们需要调用super.clone()方法来创建一个新的对象,并将原始对象中的属性复制到这个新对象中。 下面是一个示例代码,演示了如何在Java中实现对象的克隆: ``` public class MyClass implements Cloneable { private int value; public MyClass(int value) { this.value = value; } public int getValue() { return value; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } ``` 在这个示例代码中,我们实现了一个MyClass类,并重写了clone()方法。在这个方法中,我们调用了super.clone()方法来创建一个新的对象,并返回这个新对象。由于我们的类实现了Cloneable接口,因此它可以被克隆。 使用这个类进行克隆的代码如下: ``` MyClass obj1 = new MyClass(10); MyClass obj2 = (MyClass) obj1.clone(); System.out.println(obj1.getValue()); // 输出10 System.out.println(obj2.getValue()); // 输出10 ``` 在这个代码中,我们创建了一个MyClass对象obj1,并将其克隆为obj2。由于这两个对象具有相同的属性和方法,因此它们的输出结果也是相同的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值