`

java中的clone机制及序列化

阅读更多

    在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也就是说,AB是两个独立的对象,但B的初始值是由A对象确定的。在这种情况下常常使用clone。当然你完全可以new一个新的,让后再进行赋值。但应用clone会有如下的好处:

     1、实现clone方法比较简单、方便。

     2、Object类的clone()一个native方法,native方法的效率一般来说都是远高于java中的非native方法,因此clone方法是高效的。

    注意;通过序列化的方式也可以实现clone。如果一个对象包含复杂类型的变量时,可用序列化或深度clone来实现对象的clone。

浅度复制和深度复制

  
    在java中,对于基本类型的数据可采用浅度复制的方式进行对象的复制,其中做法就是直接继承Cloneable接口,调用Object类的clone()方法就可以了。而对于非基本类型的数据,复制方法只能采用深度复制或序列化的方式进行复制。
    典型的实例:
/**
 * 
 * @功能   羊对象类  
 * @创建人   gao_jie
 * @创建日期 Jun 25, 2009
 * @版本     1.0
 * 
 */
public class Sheep implements Cloneable {
	
	private String name;//名字

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#clone()
	 */
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}

public class Sheepfold implements Cloneable {
	 public Sheep sheep;//羊对象
	 public String name;//羊圈名字
	 public int number;//数量

	 public Sheepfold() {
		 this.sheep = new Sheep();
	 }
	/* (non-Javadoc)
	 * @see java.lang.Object#clone()
	 */
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}

public class Test {
	public static void main(String[] args) {
		// 声明一个小羊圈对象
		Sheepfold smallFold = new Sheepfold();
		smallFold.name = "小羊圈";
		smallFold.number = 10;
		smallFold.sheep.setName("小羊");
		// 复制羊圈
		Sheepfold bigFold = null;
		try {
			bigFold = (Sheepfold) smallFold.clone();
		} catch (CloneNotSupportedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		bigFold.name="大羊圈";
		bigFold.number=100;
		bigFold.sheep.setName("大羊");
		
		System.out.println("小羊圈输出信息如下:");
		System.out.println("smallFold.name="+smallFold.name);
		System.out.println("smallFold.number="+smallFold.number);
		System.out.println("smallFold.sheep="+smallFold.sheep.getName());
		System.out.println("大羊圈输出信息如下:");
		System.out.println("bigFold.name="+bigFold.name);
		System.out.println("bigFold.number="+bigFold.number);
		System.out.println("bigFold.sheep="+bigFold.sheep.getName());
	}
}
测试结果:
小羊圈输出信息如下:
smallFold.name=小羊圈
smallFold.number=10
smallFold.sheep=大羊
大羊圈输出信息如下:
bigFold.name=大羊圈
bigFold.number=100
bigFold.sheep=大羊
 
显然上面的这种复制是失败的,因为改动第二个对象中的名字后第一个对象的名字也发生了变化。要实现正确的复制,必须采用深度复制。其sheepfold类中clone方法的代码应改为如下:

把上面的例子改成深度clone很简单,只需将Sheepfold的clone()方法改为如下即可:
    public Object clone() throws CloneNotSupportedException {
        Sheepfold fold = (Sheepfold)super.clone();
        sheep = (Sheep)fold.sheep.clone();
        return fold;
    }
 另外,采用序列化也可以实现深度复制的效果。
代码如下:

/**
 * 
 * @功能   羊对象类  
 * @创建人   gao_jie
 * @创建日期 Jun 25, 2009
 * @版本     1.0
 * 
 */
public class Sheep implements Serializable{
	
	private String name;//名字

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

public class Sheepfold implements Cloneable, Serializable {
	public Sheep sheep;// 羊对象
	public String name;// 羊圈名字
	public int number;// 数量

	public Sheepfold() {
		this.sheep = new Sheep();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#clone()
	 */
	public Object clone() throws CloneNotSupportedException {
		try {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(bos);
			oos.writeObject(this);
			// 将流序列化
			ByteArrayInputStream bis = new ByteArrayInputStream(bos
					.toByteArray());
			ObjectInputStream ois = new ObjectInputStream(bis);
			return ois.readObject();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
}
测试类
public class Test {
	public static void main(String[] args) {
		// 声明一个小羊圈对象
		Sheepfold smallFold = new Sheepfold();
		smallFold.name = "小羊圈";
		smallFold.number = 10;
		smallFold.sheep.setName("小羊");
		// 复制羊圈
		Sheepfold bigFold = null;
		try {
			bigFold = (Sheepfold) smallFold.clone();
		} catch (CloneNotSupportedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		bigFold.name="大羊圈";
		bigFold.number=100;
		bigFold.sheep.setName("大羊");
		
		System.out.println("小羊圈输出信息如下:");
		System.out.println("smallFold.name="+smallFold.name);
		System.out.println("smallFold.number="+smallFold.number);
		System.out.println("smallFold.sheep="+smallFold.sheep.getName());
		System.out.println("大羊圈输出信息如下:");
		System.out.println("bigFold.name="+bigFold.name);
		System.out.println("bigFold.number="+bigFold.number);
		System.out.println("bigFold.sheep="+bigFold.sheep.getName());
	}
}
测试结果:
小羊圈输出信息如下:
smallFold.name=小羊圈
smallFold.number=10
smallFold.sheep=小羊
大羊圈输出信息如下:
bigFold.name=大羊圈
bigFold.number=100
bigFold.sheep=大羊
 显然,序列化可以实现深度复制的效果,但每个非基本类型对象都必须是可序列化的。而设计模式中的原型啊模式也就是实现深度复制,因此,原型模式可以采用深度复制和序列化两种方式来实现。

       

分享到:
评论

相关推荐

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

    在本文中,我们将深入探讨关于Java对象序列化你可能不知道的五件事情,这些知识点对于理解和优化你的Java应用程序至关重要。 1. **序列化的意义与用途** Java对象序列化不仅用于持久化对象状态,还能在网络传输中...

    07-Java序列化面试题(10题)-新增.pdf

    在 Java 中,序列化是一种用于处理对象流的机制,它可以将对象的内容进行流化,使其可以被读写和传输。下面是 10 个与 Java 序列化相关的面试题目: 1. 什么是 Java 序列化,如何实现 Java 序列化? Java 序列化是...

    JAVA_高级特性(hashCode,clone,比较器,Class反射,序列化)

    ### Java 高级特性详解 #### 一、`hashCode` ...正确地重写 `equals` 和 `hashCode` 方法、使用 `Comparator` 进行排序、利用反射机制和序列化技术,以及实现 `clone` 方法都是开发高质量 Java 应用程序的重要技能。

    java Clone

    如果对象的成员变量是不可克隆的(如`final`字段或不可克隆的第三方类),则可能需要采用其他策略,比如序列化和反序列化,或者手动创建新对象并复制属性。 总之,Java的`clone`机制提供了复制对象的能力,通过实现...

    KryoJava序列化和克隆框架具有快速高效自动的特点

    7. **兼容性**:Kryo虽然不是Java标准的序列化机制,但它能很好地与其他Java库集成,如Google的Protocol Buffers或Apache Avro。 **Kryo的使用示例** 1. **初始化Kryo实例**: ```java Kryo kryo = new Kryo(); ...

    (完整word版)java6个机制.doc

    Java 语言中的六个核心机制包括克隆、序列化、多线程、异常处理、垃圾回收以及反射。在这里,我们将详细探讨前三个机制。 首先,让我们来看看克隆机制。克隆在编程中指的是复制一个对象并在内存中创建其副本。在 ...

    java-6个机制.doc

    Java的六个核心机制是编程中不可或缺的部分,它们包括克隆机制、序列化机制、多线程机制、反射机制以及垃圾回收机制和异常处理机制。在这篇文章中,我们将深入探讨前三个机制。 首先,克隆机制允许我们在内存中复制...

    Java利用序列化实现对象深度clone的方法

    有多种方式可以实现对象克隆,其中一种就是通过Java的序列化机制。序列化是将对象的状态转换为字节流的过程,而反序列化则是将字节流恢复为对象状态的过程。这种机制可以用来实现深度克隆,即不仅克隆对象本身,还...

    Java clone方法详解及简单实例

    Java中的`clone`方法是Java语言提供的一种复制对象的机制,它允许创建一个现有对象的副本,这个副本具有与原始对象相同的状态,但它们是独立的实体,对其中一个对象的修改不会影响另一个。`clone`方法是Java `Object...

    JAVA创建对象的四种方法

    -java 创建对象的四种方法是指在 Java 中创建对象的不同方式,它们分别是使用 new 语句创建对象、使用反射机制创建对象、使用 clone() 方法创建对象和使用反序列化机制创建对象。 - 使用 new 语句创建对象是 Java ...

    Java面试指南.pdf

    - Java创建对象的方式:可以通过new关键字直接创建,也可以通过反射机制、clone方法或反序列化等方式创建。 - 序列化和反序列化:序列化是将对象的状态信息转换为可以存储或传输的形式的过程,反序列化则是把序列...

    Java Clone深拷贝与浅拷贝的两种实现方法

    深拷贝可以使用多种方法来实现,例如使用序列化和反序列化、使用复制构造函数、使用 clone() 方法等。 例如,我们可以使用下面的代码来实现深拷贝: ```java public class Student implements Cloneable { ...

    2023编程精选题库:Java面试题集及参考答案.docx

    Java 中创建对象的几种方式包括采用 new、通过反射、采用 clone、通过序列化机制等方式。 九、switch 语句 switch 语句可以使用 byte、short、char、int 或者其对应的封装类、Enum 类型和 String 类型。从 Java ...

    java List 深度复制方法

    以下是一个简单的深复制示例,使用了Java的序列化机制: ```java import java.io.*; public class DeepCopyExample { public static <T> List<T> deepCopy(List<T> originalList) throws IOException, ...

    笔试Java3.doc

    Java 编程中的多个基础知识点,涵盖了线程、同步、序列化、流、文件读写、Socket 通讯、SQL、 PrepardStatement、Java 反射机制、Eclipse 安装、Javadoc、匈牙利命名方式、事件监听模型、SQL 联接数据、JDK1.5 新...

    Java面试小抄第一版 By 库森.pdf

    在《Java面试小抄第一版》中,作者库森详细整理了一系列Java编程语言和相关技术栈的面试知识点,这些知识点覆盖了Java基础、面向对象、异常处理、数据结构、集合框架、泛型、反射、序列化等多个方面,是Java开发者...

    java深度克隆

    这种方法利用Java的序列化机制实现深度克隆。具体步骤如下: 1. **实现Serializable接口**:需要被克隆的类必须实现`Serializable`接口。 2. **序列化对象**:将对象转换为字节流。 3. **反序列化对象**:从字节流...

    java四种创建对象的方式

    Java中创建对象主要有四种显式的方式,分别是使用new关键字、反射机制、克隆克隆方法以及反序列化手段。每种方法都有其特定的使用场景和特点,以下是这些方法的详细说明: 1. 使用new关键字创建对象 这是最常见也是...

Global site tag (gtag.js) - Google Analytics