`
阅读更多

一、使用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 编程入门思考

    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 ...

    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_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 ...

    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 深层拷贝 DeepCopy的使用详解

    最近需要用到比较两个对象属性的变化,其中一个是oldObj,另外一个是newObj,oldObj是newObj的前一个状态,所以需要在newObj的某个状态时,复制一个一样的对象,由于JAVA不支持深层拷贝,因此专门写了一个方法

    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 ...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例111 Java对象的深克隆 137 实例112 序列化与对象克隆 139 实例113 深克隆效率的比较 141 实例114 transient关键字的应用 143 5.7 接口和内部类 145 实例115 使用sort()方法排序 145 实例116 简化compareTo()方法...

    kryo:Java二进制序列化和克隆:快速,高效,自动

    Kryo是用于Java的快速高效的二进制对象图序列化框架。 该项目的目标是高速,小尺寸和易于使用的API。 每当需要将对象持久保存到文件,数据库还是通过网络时,该项目都是有用的。 Kryo还可以执行自动的深层和浅层...

    ThinkInJava

    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 ...

    thinkinjava

    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 ...

    bingo-bean:对象拷贝,目标是比dozer更快,功能更强大,更完整的支持泛型

    bingo-bean对象拷贝,目标是比dozer更快,功能更强大,更完整的支持泛型1、该项目是复制对象的工具,创建目的是:a)、比Dozer、FastJson更快,占用内存更小b)、不同类型间的复制,包括对自定义泛型的深层识别,参见...

    硒页面对象发电机「Selenium Page Object Generator」-crx插件

    选项按钮的机制*代码重组版本1.1.2 *使用更好和更广泛的机制来获取标签文本版本1.1.1 *取消单击选项按钮的默认操作*重新排列对象深层复制以优雅地消亡*基于兄弟姐妹使用更特定CSS选择器和元素类型*考虑输入按钮的...

Global site tag (gtag.js) - Google Analytics