`
阅读更多

一、使用clone复制

public class CloneTest {
   public static void main(String[] args) {
      Person p1 = new Person("张居正",10,new StringBuffer("男"),new Address("北京",3008));
      System.out.println("被clone之前的p1=="+p1);
      Person p2 = (Person) p1.clone();
      System.out.println("克隆产生的p2=="+p2);
      System.out.println("***********************************");
      p2.name = "戚继光";
      p2.age = 12;
      p2.sex.append("猛男");
      p2.address.city = "天津";
      p2.address.number = 9000;
      System.out.println("改变p2的属性之后:");
      System.out.println("p1=="+p1);
      System.out.println("p2=="+p2);
      System.out.println("p1和p2的属性都不相等,证明确实实现了深层复制!");
   }
 
}
//Address类型属于能够直接调用clone方法实现深层复制的其他类型
class Address implements Cloneable{
   public String city;
   public int number;
   public Address(String city,int number){
      this.city = city;
      this.number = number;
   }
   @Override
   public Object clone()
        throws CloneNotSupportedException{
      return super.clone();
   }
   @Override
   public String toString(){
      return "city="+city+";number="+number;
   }
}
 
//用于序列化的类
//第一,必须实现java.lang.Cloneable接口
class Person implements Cloneable{
   //第二,所有属性必须是基本数据类型、String、StringBuffer类型,或者能够直接调用clone方法实现深度复制的其他类型
   //注意:StringBuffer类型不能够直接调用clone方法实现直接复制
   public String name;
   public int age;
   public StringBuffer sex;
   public Address address;
   public Person(
        String name,int age,
        StringBuffer sex,
        Address address){
      this.name = name;
      this.age = age;
      this.sex = sex;
      this.address = address;
   }
   //第三,必须重写clone方法
   @Override
   public Object clone(){
      Person p = null;
      try {
        //第四,对于基本数据类型和String类型,在调用super.clone()方法时,就已经复制成功了
        p = (Person) super.clone();
      } catch (CloneNotSupportedException e) {
        e.printStackTrace();
        return null;
      }
      //第五,如果属性是StringBuffer类型,则需要使用下面是形式再次给属性赋值
      p.sex = new StringBuffer(this.sex.toString());
      //第六,如果实行不是基本数据类型、String、StringBuffer类型,则使用一下进行属性的深层复制
      try {
        p.address = (Address) address.clone();
      } catch (CloneNotSupportedException e) {
        p.address = null;
        e.printStackTrace();
      }
      return p;
   }
   @Override
   public String toString(){
      return "name="+name+";age="+age+";sex="+sex.toString()+";address={"+address+"}";
   }
}

 

 

运行结果:

被clone之前的p1==name=张居正;age=10;sex=男;address={city=北京;number=3008}
克隆产生的p2==name=张居正;age=10;sex=男;address={city=北京;number=3008}
***********************************
改变p2的属性之后:
p1==name=张居正;age=10;sex=男;address={city=北京;number=3008}
p2==name=戚继光;age=12;sex=男猛男;address={city=天津;number=9000}

 

p1p2的属性都不相等,证明确实实现了深层复制!

二、使用序列化复制

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
 
public class SerializableTest {
   public static void main(String[] args)
        throws IOException, ClassNotFoundException {
      Person p1 = new Person("张居正",10,new StringBuffer("男"));
      System.out.println("序列化之前的p1=="+p1);
      byte [] bytes = serializeToByte(p1);
      Person p2 = (Person)deserializeToObject(bytes);
      System.out.println("反序列化之后的p2=="+p2);
      System.out.println("***********************************");
      p2.name = "戚继光";
      p2.age = 12;
      p2.sex.append("猛男");
      System.out.println("改变p2的属性之后:");
      System.out.println("p1=="+p1);
      System.out.println("p2=="+p2);
      System.out.println("p1和p2的属性都不相等,证明确实实现了深层复制!");
   }
  
   //将Java对象序列化为byte数组
   public static byte [] serializeToByte(Object obj)
        throws IOException{
      ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); 
      ObjectOutputStream out = new ObjectOutputStream(byteOut); 
      out.writeObject(obj);
      return byteOut.toByteArray();
   }
  
   //将byte数组反序列化为Java对象
   public static Object deserializeToObject(byte [] bytes)
        throws IOException, ClassNotFoundException{
      ByteArrayInputStream byteIn = new ByteArrayInputStream(bytes); 
      ObjectInputStream in =new ObjectInputStream(byteIn);
      return in.readObject();
   }
}
 
//用于序列化的类,必须实现java.lang.Serializable接口
class Person implements Serializable{
   public String name;
   public int age;
   public StringBuffer sex;
   public Person(String name,int age,StringBuffer sex){
      this.name = name;
      this.age = age;
      this.sex = sex;
   }
@Override
   public String toString(){
      return "name="+name+";age="+age+";sex="+sex.toString();
   }
}

 

注意:被序列化的对象的类必须已经实现java.lang.Serializable接口。

运行结果:

序列化之前的p1==name=张居正;age=10;sex=男
反序列化之后的p2==name=张居正;age=10;sex=男
***********************************
改变p2的属性之后:
p1==name=张居正;age=10;sex=男
p2==name=戚继光;age=12;sex=男猛男

 

p1p2的属性都不相等,证明确实实现了深层复制!

 

参考文章:http://www.ibm.com/developerworks/cn/java/l-jpointer/index.html

 

 

分享到:
评论

相关推荐

    Java对象的复制克隆

    Java中的对象复制与克隆是程序开发中常见的需求,主要用于创建一个对象的副本,而不会影响原始对象的状态。这里主要讨论两种类型的对象拷贝:浅拷贝和深拷贝。 浅拷贝,也称为表面拷贝,是创建一个新的对象,然后将...

    关于Java对象序列化您不知道的5件事Java开发Java

    Java对象序列化是Java开发中的一个重要概念,它允许我们将Java对象转换为字节流,以便存储、传输或在不同时间点恢复。以下是五个可能不为人知的关于Java对象序列化的知识点,这些知识点对于深入理解Java开发至关重要...

    java_经典多线程编程

    - **深层复制**:递归地复制了所有的对象,确保复制的对象完全独立于原始对象。 - **实现方式**:可以通过实现`Cloneable`接口并重写`clone()`方法来实现浅层复制,而对于深层复制,可以通过序列化和反序列化来...

    Java教程.doc

    基本类型的赋值是将一个值赋值给另一个值,而对象之间的赋值是将一个对象的reference从某处复制到另一处,可能会导致别名现象。 解决别名的方法 可以通过clone方法来解决别名问题。clone方法可以制作某个对象的...

    Java深浅clone

    因此,所有Java对象默认都具备`clone()`能力。但是,为了使用它,我们需要覆盖`clone()`方法,并且确保类实现了`Cloneable`接口,以避免抛出异常。 测试代码通常会包括以下步骤: 1. 实现`Cloneable`接口。 2. ...

    java 编程入门思考

    A.1.3 传递和使用Java对象 A.1.4 JNI和Java违例 A.1.5 JNI和线程处理 A.1.6 使用现成代码 A.2 微软的解决方案 A.3 J/Direct A.3.1 @dll.import引导命令 A.3.2 com.ms.win32包 A.3.3 汇集 A.3.4 编写回调函数 A.3.5 ...

    Java中的数组复制(clone与arraycopy)代码详解

    clone方法执行的是浅表复制,而不是深层复制操作。 使用clone方法需要实现java.lang.Cloneable接口,并重写protected方法clone。如果没有实现Clonebale接口会抛出CloneNotSupportedException。在克隆java对象的时候...

    Thinking in Java 中文第四版+习题答案

    A.1.3 传递和使用Java对象 A.1.4 JNI和Java违例 A.1.5 JNI和线程处理 A.1.6 使用现成代码 A.2 微软的解决方案 A.3.1 @dll.import引导命令 A.3.2 com.ms.win32包 A.3.3 汇集 A.3.4 编写回调函数 A.3.5 其他J/Direct...

    Java初学者入门教学

    A.1.3 传递和使用Java对象 A.1.4 JNI和Java违例 A.1.5 JNI和线程处理 A.1.6 使用现成代码 A.2 微软的解决方案 A.3 J/Direct A.3.1 @dll.import引导命令 A.3.2 com.ms.win32包 A.3.3 汇集 A.3.4 编写回调函数 A.3.5 ...

    java联想(中文)

    A.1.3 传递和使用Java对象 A.1.4 JNI和Java违例 A.1.5 JNI和线程处理 A.1.6 使用现成代码 A.2 微软的解决方案 A.3 J/Direct A.3.1 @dll.import引导命令 A.3.2 com.ms.win32包 A.3.3 汇集 A.3.4 编写回调函数 A.3.5 ...

    U10316040_HW5_15_10:这是一个了解深层复制的专案

    在IT领域,尤其是在编程中,理解“深层复制”是一个至关重要的概念,特别是在处理对象和数据结构时。这个项目,"U10316040_HW5_15_10",显然是一个旨在帮助学习者深入理解深层复制的实践任务。在Java语言环境下,...

    JAVA_Thinking in Java

    A.1.3 传递和使用Java对象 A.1.4 JNI和Java违例 A.1.5 JNI和线程处理 A.1.6 使用现成代码 A.2 微软的解决方案 A.3 J/Direct A.3.1 @dll.import引导命令 A.3.2 com.ms.win32包 A.3.3 汇集 A.3.4 编写回调函数 A.3.5 ...

    Thinking in Java简体中文(全)

    A.1.3 传递和使用Java对象 A.1.4 JNI和Java违例 A.1.5 JNI和线程处理 A.1.6 使用现成代码 A.2 微软的解决方案 A.3 J/Direct A.3.1 @dll.import引导命令 A.3.2 com.ms.win32包 A.3.3 汇集 A.3.4 编写回调函数 A.3.5 ...

    JAVA 深层拷贝 DeepCopy的使用详解

    然而,Java的标准库并不直接支持深拷贝,因为Java的`clone()`方法默认执行的是浅拷贝,只复制对象本身而不复制其引用的对象。因此,开发者需要自定义实现深拷贝机制。本文将详细讲解如何在Java中实现深拷贝,并提供...

    java深度历险--学习深入了解java的好书

    总的来说,《Java深度历险》是一本适合有基础的Java开发者阅读的书籍,它能带领你探索Java的深层世界,提升你的技术水平。通过学习,你不仅可以理解Java的运作机制,还能掌握解决实际问题的技巧,为你的Java开发事业...

    java_javasecore1_day05

    - 对象序列化是指将Java对象的状态转换为字节序列的过程,以便于存储或在网络中传输。 - 反序列化则是将字节序列还原为原始Java对象的过程。 - 序列化和反序列化涉及使用`java.io.Serializable`接口标记可序列化的类...

    JAVA_Thinking in Java(中文版 由yyc,spirit整理).chm

    A.1.3 传递和使用Java对象 A.1.4 JNI和Java违例 A.1.5 JNI和线程处理 A.1.6 使用现成代码 A.2 微软的解决方案 A.3 J/Direct A.3.1 @dll.import引导命令 A.3.2 com.ms.win32包 A.3.3 汇集 A.3.4 编写回调函数 A.3.5 ...

    Think in Java(中文版)chm格式

    A.1.3 传递和使用Java对象 A.1.4 JNI和Java违例 A.1.5 JNI和线程处理 A.1.6 使用现成代码 A.2 微软的解决方案 A.3 J/Direct A.3.1 @dll.import引导命令 A.3.2 com.ms.win32包 A.3.3 汇集 A.3.4 编写回调...

    Thinking in Java(中文版 由yyc,spirit整理).chm

    A.1.3 传递和使用Java对象 A.1.4 JNI和Java违例 A.1.5 JNI和线程处理 A.1.6 使用现成代码 A.2 微软的解决方案 A.3 J/Direct A.3.1 @dll.import引导命令 A.3.2 com.ms.win32包 A.3.3 汇集 A.3.4 编写回调函数 A.3.5 ...

Global site tag (gtag.js) - Google Analytics