`
ncs123
  • 浏览: 99675 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Cloneable 和 clone()的总结和使用

    博客分类:
  • J2SE
阅读更多
一.Cloneable 的用途
  Cloneable和Serializable一样都是标记型接口,它们内部都没有方法和属性,implements Cloneable表示该对象能被克隆,能使用Object.clone()方法。如果没有implements Cloneable的类调用Object.clone()方法就会抛出CloneNotSupportedException。

二.克隆的分类
  (1)浅克隆(shallow clone),浅拷贝是指拷贝对象时仅仅拷贝对象本身和对象中的基本变量,而不拷贝对象包含的引用指向的对象。
  (2)深克隆(deep clone),深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。

举例区别一下:对象A1中包含对B1的引用,B1中包含对C1的引用。浅拷贝A1得到A2,A2中依然包含对B1的引用,B1中依然包含对C1的引用。深拷贝则是对浅拷贝的递归,深拷贝A1得到A2,A2中包含对B2(B1的copy)的引用,B2中包含对C2(C1的copy)的引用。

三.克隆的举例
  要让一个对象进行克隆,其实就是两个步骤:
  1. 让该类实现java.lang.Cloneable接口;
  2. 重写(override)Object类的clone()方法。

public class Wife implements Cloneable {
	private int id;
	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public Wife(int id,String name) {
		this.id = id;
		this.name = name;
	}

	@Override
	public int hashCode() {//myeclipse自动生成的
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {//myeclipse自动生成的
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Wife other = (Wife) obj;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

	@Override
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}

	/**
	 * @param args
	 * @throws CloneNotSupportedException 
	 */
	public static void main(String[] args) throws CloneNotSupportedException {
		Wife wife = new Wife(1,"wang");
		Wife wife2 = null;
		wife2 = (Wife) wife.clone();
		System.out.println("class same="+(wife.getClass()==wife2.getClass()));//true
		System.out.println("object same="+(wife==wife2));//false
		System.out.println("object equals="+(wife.equals(wife2)));//true
	}
}


四.浅克隆的举例
public class Husband implements Cloneable {
	private int id;
	private Wife wife;
	
	public Wife getWife() {
		return wife;
	}

	public void setWife(Wife wife) {
		this.wife = wife;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public Husband(int id) {
		this.id = id;
	}

	@Override
	public int hashCode() {//myeclipse自动生成的
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}

	@Override
	public boolean equals(Object obj) {//myeclipse自动生成的
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Husband other = (Husband) obj;
		if (id != other.id)
			return false;
		return true;
	}

	/**
	 * @param args
	 * @throws CloneNotSupportedException 
	 */
	public static void main(String[] args) throws CloneNotSupportedException {
		Wife wife = new Wife(1,"jin");
		Husband husband = new Husband(1);
		Husband husband2 = null;
		husband.setWife(wife);
		husband2 = (Husband) husband.clone();
		System.out.println("husband class same="+(husband.getClass()==husband2.getClass()));//true
		System.out.println("husband object same="+(husband==husband2));//false
		System.out.println("husband object equals="+(husband.equals(husband)));//true
		System.out.println("wife class same="+(husband.getWife().getClass()==husband2.getWife().getClass()));//true
		System.out.println("wife object same="+(husband.getWife()==husband2.getWife()));//true
		System.out.println("wife object equals="+(husband.getWife().equals(husband.getWife())));//true
	}
}


五.深克隆的举例
  如果要深克隆,需要重写(override)Object类的clone()方法,并且在方法内部调用持有对象的clone()方法;注意如下代码的clone()方法
public class Husband implements Cloneable {
	private int id;
	private Wife wife;
	
	public Wife getWife() {
		return wife;
	}

	public void setWife(Wife wife) {
		this.wife = wife;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public Husband(int id) {
		this.id = id;
	}

	@Override
	public int hashCode() {//myeclipse自动生成的
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		Husband husband = (Husband) super.clone();
		husband.wife = (Wife) husband.getWife().clone();
		return husband;
	}

	@Override
	public boolean equals(Object obj) {//myeclipse自动生成的
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Husband other = (Husband) obj;
		if (id != other.id)
			return false;
		return true;
	}

	/**
	 * @param args
	 * @throws CloneNotSupportedException 
	 */
	public static void main(String[] args) throws CloneNotSupportedException {
		Wife wife = new Wife(1,"jin");
		Husband husband = new Husband(1);
		Husband husband2 = null;
		husband.setWife(wife);
		husband2 = (Husband) husband.clone();
		System.out.println("husband class same="+(husband.getClass()==husband2.getClass()));//true
		System.out.println("husband object same="+(husband==husband2));//false
		System.out.println("husband object equals="+(husband.equals(husband)));//true
		System.out.println("wife class same="+(husband.getWife().getClass()==husband2.getWife().getClass()));//true
		System.out.println("wife object same="+(husband.getWife()==husband2.getWife()));//false
		System.out.println("wife object equals="+(husband.getWife().equals(husband.getWife())));//true
	}
}

但是也有不足之处,如果Husband内有N个对象属性,突然改变了类的结构,还要重新修改clone()方法。解决办法:可以使用Serializable运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。

参考java创建对象的第四种方法:
http://ncs123.iteye.com/blog/1775661
分享到:
评论

相关推荐

    Java深浅clone

    Java深浅clone测试代码 流拷贝 Cloneable

    Cloneable:使用C#Source Generator自动生成克隆方法

    安装可克隆您应该安装 : Install-Package Cloneable或者通过 .NET Core 命令行界面: dotnet add package Cloneable来自包管理器控制台或 .NET Core CLI 的任一命令都将下载并安装 Cloneable 和所有必需的依赖项。...

    bigcoder84#study-notes#_4Object中的clone方法1

    Object类中的clone方法clone()方法的作用克隆方法用于创建对象的拷贝,为了使用clone方法,类必须实现java.lang.Cloneable接口

    cloneable-readable:安全地克隆可读流

    'use strict'var cloneable = require ( 'cloneable-readable' )var fs = require ( 'fs' )var pump = require ( 'pump' )var stream = cloneable ( fs . createReadStream ( './package.json' ) )pump ( stream . ...

    java克隆对象(两种方法)

    java的两种深度克隆方法,1cloneTest是用Cloneable接口的clone方法实现(对象必须要实现cloneable接口).2cloneSerialize.java是用对象流写对象到byte数组中,然后从byte数组中取得对象.(对象必须要实现serializble接口)

    06 类与对象31

    1.在类定义中实现Cloneable接口 2.在类中覆盖基类的clone()方法,声明为public,注意 4.使用clone方法时要进行强制转换 1.“浅克隆

    java设计模式【之】原型模式、深拷贝与浅拷贝【源码】【场景:克隆羊】

    * 需要被克隆的 class类, 重写Object中的clone()方法,并实现Cloneable接口(否则报错 CloneNotSupportedException) * 注意: * 1.被克隆对象.clone()出的对象,是被克隆对象的当前状态 * 2.被克隆对象 如果...

    结合JVM解读浅拷贝和深拷贝

    java.lang.Cloneable和java.io.Serializable一样属于标记型接口,没有定义任何方法和属性。 一个类想要使用克隆方法 重写clone()方法,因为Object的clone()的修饰符是protected; @HotSpotIntrinsicCandidate ...

    二十三种设计模式【PDF版】

    使用类再生的两个方式:组合(new)和继承(extends),这个已经在 thinking in java中提到过. 设计模式之 Proxy(代理) 以 Jive 为例,剖析代理模式在用户级别授权机制上的应用 设计模式之 Facade(门面?) 可扩展的使用...

    GOF23之原型模式

    一、核心作用: ...实现Cloneable接口和重写clone()方法 四、示例: 一、浅克隆 实体类: package com.hezeu.prototype; import java.io.Serializable; import java.util.Date; /** *@Classname She

    新手入门写Java程序的三十个基本规则

    新手入门写Java程序的三十个基本规则 (1) 类名首字母应该大写。字段、方法以及对象(句柄)的首字母应小写。对于所有标识符,其中包含的所有单词都应紧靠在... clone()(implement Cloneable)  implement Serializable

    leetcode分类-DesignPatternAndAlgorithm:常用设计模式和算法,练习用

    leetcode 分类 DesignPatternAndAlgorithm 常用设计模式和算法,练习用。...原型模式:与new一个新对象不同,原型模式是clone出一个新对象。已与java融为一体,实现Cloneable接口。分为深拷贝和浅拷贝。 抽

    java编程常见问题

    当没有实现Cloneable接口或者不支持克隆方法时,调用其clone()方法则抛出该异常。 47.java.lang.EnumConstantNotPresentException 枚举常量不存在异常。当应用试图通过名称和枚举类型访问一个枚举对象,但该枚举对象...

    Java浅克隆与深克隆

    public class ShallowClone implements Cloneable { public String name; public String[] name2; public ShallowClone() { name2 = new String[2]; } public Object clone() { ShallowClone o = null; try...

Global site tag (gtag.js) - Google Analytics