java中对象的拷贝_java中的对象拷贝

java中clone()方法的的作用是Creates and returns a copy of this object。

The general intent is that, for any object {@code x}, the expression:

x.clone() != x,will be true

x.clone().getClass() == x.getClass(),will be true

x.clone().equals(x),will be true 其中第一点必须是不等的,也就是说复制出来的对象有自己单独的内存地址;第二点表明clone出来的java对象的java类型是相同的,不是强制要求的;第三点表明clone出来的对象使用equals方法是相等的,但不是强制要求的。

下来我们来做个试验:

public class Student implements Cloneable{

private String name;

private int age;

private Address address;

public Student(String name, int age, Address address){

this.name = name;

this.age = age;

this.address = address;

}

@Override

protected Object clone() throws CloneNotSupportedException{

return super.clone();

}

}

public class Address {

private String city;

private String country;

public Address(String city, String country) {

this.city = city;

this.country = country;

}

}

测试一下,是不是如我们jdk文档所说的

public class Test {

public static void main(String[] args) throws CloneNotSupportedException{

Address address = new Address("wuhan","china");

Student student = new Student("jack",25,address);

Student cloneStuednt = (Student) student.clone();

System.out.println(student != cloneStuednt);

System.out.println(student.getClass() == cloneStuednt.getClass());

System.out.println(cloneStuednt.equals(student));

}

}

输出:

true

true

false

如果这个时候我们更改原对象中的状态又会发生什么呢?

public class Test {

public static void main(String[] args) throws CloneNotSupportedException{

Address address = new Address("wuhan","china");

Student student = new Student("jack",25,address);

Student cloneStuednt = (Student) student.clone();

student.getAddress().setCity("nanjing");

System.out.println(cloneStuednt.getAddress().getCity());

}

}

输出

nanjing

我们会发现如果改变了原对象,那么克隆出来的对象也发生了变化,在某些情况下,我们并不希望这种事情发生。其实这是由于浅克隆造成的,那么如何可以避免浅克隆

deep clone

上面这个例子浅克隆的原因是由于Address对象没有实现Cloneable接口,如果Address对象也实现了这个接口,并重写了clone()方法,便可以解决这个问题。

public class Address implements Cloneable{

private String city;

private String country;

public Address(String city, String country){

this.city = city;

this.country = country;

}

@Override

protected Object clone() throws CloneNotSupportedException{

return super.clone();

}

public String getCity(){

return city;

}

public void setCity(String city){

this.city = city;

}

public String getCountry(){

return country;

}

public void setCountry(String country){

this.country = country;

}

}

public class Student implements Cloneable{

private String name;

private int age;

private Address address;

public Student(String name, int age, Address address){

this.name = name;

this.age = age;

this.address = address;

}

@Override

protected Object clone() throws CloneNotSupportedException{

Student clone = (Student) super.clone();

clone.setAddress((Address) clone.getAddress().clone());

return clone;

}

public String getName(){

return name;

}

public void setName(String name){

this.name = name;

}

public int getAge(){

return age;

}

public void setAge(int age){

this.age = age;

}

public Address getAddress(){

return address;

}

public void setAddress(Address address){

this.address = address;

}

}

最后我们再次运行一下测试类,会发现这次是我们所期望的结果

public class Test {

public static void main(String[] args) throws CloneNotSupportedException{

Address address = new Address("wuhan","china");

Student student = new Student("jack",25,address);

Student cloneStuednt = (Student) student.clone();

student.getAddress().setCity("nanjing");

System.out.println(cloneStuednt.getAddress().getCity());

}

}

输出

wuhan

这的确完成了deep clone,但我们并不推荐这样去做,在实际的项目中很可能也无法让每个类都去实现Cloneable接口重写clone方法。那么是否还有其他的方法可以完成深拷贝吗? apache的 org.apache.commons.lang.SerializationUtils类有一种方法,使用序列化和反序列化的方法实现了深拷贝。主要的代码是:

ByteArrayOutputStreambos= new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(object);

oos.flush();

oos.close();

bos.close();byte[]byteData= bos.toByteArray();ByteArrayInputStreambais= new ByteArrayInputStream(byteData);(Object) object = (Object) new ObjectInputStream(bais).readObject();

这种方法我感觉应该是最简单的方法实现深拷贝的方法。

另外还有另外一种方法实现了深拷贝,通过java反射区一个个去get/set设置java对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值