`
yangwn
  • 浏览: 77313 次
  • 性别: Icon_minigender_2
  • 来自: 大连
社区版块
存档分类
最新评论
  • icewubin: kimmking 写道icewubin 写道Dollyn 写道 ...
    Java
  • kimmking: icewubin 写道Dollyn 写道我十分怀疑最后一条,很 ...
    Java
  • beneo: 完全忽略了一個好的JVM的優化能力 難道java是C編譯器么 ...
    Java
  • icewubin: Dollyn 写道我十分怀疑最后一条,很多编译器都会自动做类似 ...
    Java
  • Dollyn: 我十分怀疑最后一条,很多编译器都会自动做类似优化吧(不知道JD ...
    Java

JAVA中浅复制与深复制

    博客分类:
  • JAVA
阅读更多

1.概念:

浅复制与深复制概念
⑴浅复制(浅克隆)
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。

⑵深复制(深克隆)
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。

2.应用:

Java的clone()方法
⑴clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足:
  ①对任何的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象
  ②对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样
  ③如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。
⑵Java中对象的克隆
  ①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。
  ②在派生类中覆盖基类的clone()方法,并声明为public。
  ③在派生类的clone()方法中,调用super.clone()。
  ④在派生类中实现Cloneable接口。

请看如下代码:

 

public class Student implements Cloneable{
	String name;
	int age;
	Student(String name,int age){
		this.name = name;
		this.age = age;
	}
	public Object clone(){
		Object o = null;
		try{
			o = (Student)super.clone();//Object中的clone()识别出你要复制的是哪一个对象。
		}
		catch(CloneNotSupportedException e){
			System.out.println(e.toString());
		}
		return o;
	}
	public static void main(String[] args){
		Student s1 = new Student("zhangsan",18);
		Student s2 = (Student)s1.clone();
		s2.name="lisi";
		s2.age=20;
		System.out.println("name="+s1.name+","+"age="+s1.age);//修改学生2后,不影响学生1的值。
	}
}

   说明:
   ①为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?

      在运行时刻,Object 中的clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,

      将原始对象的内容一一复制到新对象的存储空间中。
   ②继承自java.lang.Object类的clone()方法是浅复制。以下代码可以证明之。

 

class Professor{
	String name;
	int age;
	Professor(String name,int age){
		this.name=name;
		this.age=age;
	}
}

class Student implements Cloneable{
	
	String name;//常量对象。
	int age;
	Professor p;//学生1和学生2的引用值都是一样的。
	Student(String name,int age,Professor p) {
		this.name=name;
		this.age=age;
		this.p=p;
	}
	public Object clone(){
		Student o=null;
		try
		{
			o=(Student)super.clone();
		}
		catch(CloneNotSupportedException e)
		{
			System.out.println(e.toString());
		}
		o.p=(Professor)p;
		return o;
	}

	public static void main(String[] args){
		Professor p=new Professor("wangwu",50);
		Student s1=new Student("zhangsan",18,p);
		Student s2=(Student)s1.clone();
		s2.p.name="lisi";
		s2.p.age=30;
		System.out.println("name="+s1.p.name+","+"age="+s1.p.age);//学生1的教授成为lisi,age为30。
	}
}

 

那应该如何实现深层次的克隆,即修改s2的信息不会影响s1的信息?代码改进如下。

package com.doit.alex.copy;

class Professor implements Cloneable{
	String name;
	int age;
	
	Professor(String name,int age){
		this.name=name;
		this.age=age;
	}
	public Object clone() {
		Object o=null;
		try{
			o=super.clone();
		}
		catch(CloneNotSupportedException e){
			System.out.println(e.toString());
		}
		return o;
	}
}

public class Student implements Cloneable {
	
	String name;
	int age;
	Professor p;
	
	Student(String name,int age,Professor p) {
		this.name=name;
		this.age=age;
		this.p=p;
	}
	public Object clone(){
		Student o=null;
		try{
			o=(Student)super.clone();
		}
		catch(CloneNotSupportedException e){
			System.out.println(e.toString());
		}
		o.p=(Professor)p.clone();
		return o;
	}
	public static void main(String[] args){
		Professor p=new Professor("wangwu",50);
		Student s1=new Student("zhangsan",18,p);
		Student s2=(Student)s1.clone();
		s2.p.name="lisi";
		s2.p.age=30;
		System.out.println("name="+s1.p.name+","+"age="+s1.p.age);//学生1的教授不改变。
	}
}

 3.利用串行化来做深复制
      把对象写到流里的过程是串行化(Serilization)过程,但是在Java程序师圈子里又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;而把对象从流中读出来的并行化(Deserialization)过程则叫做“解冻”或者“回鲜(depicking)”过程。应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。
在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。

public Object deepClone(){
	//将对象写到流里
	ByteArrayOutoutStream bo=new ByteArrayOutputStream();
	ObjectOutputStream oo=new ObjectOutputStream(bo);
	oo.writeObject(this);
	//从流里读出来
	ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
	ObjectInputStream oi=new ObjectInputStream(bi);
	return(oi.readObject());
}

   这样做的前提是对象以及对象内部所有引用到的对象都是可串行化的,否则,就需要仔细考察那些不可串行化的对象可否设成transient,从而将之排除在复制过程之外。上例代码改进如下。

package com.doit.alex.copy3;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serializable;

class Professor implements Serializable
{
	String name;
	int age;
	Professor(String name,int age)
	{
		this.name=name;
		this.age=age;
	}
}
public class Student implements Serializable{
	
	String name;	//常量对象。
	int age;
	Professor p;	//学生1和学生2的引用值都是一样的。
	
	Student(String name,int age,Professor p){
		this.name=name;
		this.age=age;
		this.p=p;
	}
	
	public <ByteArrayOutoutStream> Object deepClone() throws IOException,
	OptionalDataException,ClassNotFoundException {
		//将对象写到流里
		ByteArrayOutputStream bo =  new ByteArrayOutputStream();
		ObjectOutputStream oo = new ObjectOutputStream(bo);
		oo.writeObject(this);
		//从流里读出来
		ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
		ObjectInputStream oi=new ObjectInputStream(bi);
		return(oi.readObject());
	}
	
	public static void main(String[] args){
		Professor p=new Professor("wangwu",50);
		Student s1=new Student("zhangsan",18,p);
		Student s2 = null;
		
		try {
			s2 = (Student) s1.deepClone();
		} catch (OptionalDataException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		s2.p.name="lisi";
		s2.p.age=30;
		System.out.println("name="+s1.p.name+","+"age="+s1.p.age); //学生1的教授不改变。
	}
}

 
 

分享到:
评论

相关推荐

    android 浅复制和深复制-Java Generic Deep Copy 篇

    本文将深入探讨Java中的浅复制和深复制,并以Android为背景,结合具体的实例讲解如何实现Java泛型深拷贝。 首先,我们要理解浅复制和深复制的概念。浅复制(Shallow Copy)是指创建一个新的对象,然后将原对象引用...

    java List 深度复制方法

    在Java中,当我们使用`clone()`方法或`System.arraycopy()`进行复制时,通常得到的是浅复制的结果。这意味着原始对象和复制对象中的引用指向内存中的同一块区域。如果List中的元素是基本类型,这种复制方式是没问题...

    java的深复制与浅复制

    ### Java的深复制与浅复制 #### 一、概述 在Java编程中,对象的复制是一个常见的需求。复制对象的目的通常是为了保留一个备份或者创建一个新的实例来避免对原始对象的修改影响到其他部分的程序逻辑。Java提供了两...

    java深复制浅复制的实现源代码

    本篇文章将深入探讨Java中的深复制和浅复制概念,并通过源代码示例进行详细解析。 首先,我们理解一下深复制和浅复制的区别: 1. **浅复制(Shallow Copy)**:浅复制只是复制了对象的引用,而不是对象本身。这...

    Java深复制与浅复制.doc

    在Java编程中,复制对象是常见的操作,主要分为两种方式:浅复制(Shallow Copy)和深复制(Deep Copy)。这两种复制方式的区别在于处理对象内部引用其他对象的情况。 1. **浅复制(浅克隆)**: 浅复制是指创建一...

    Java深复制与浅复制&Clone

    在Java编程语言中,对象复制是一个常见的操作,...理解并正确使用浅复制和深复制对于开发高效、健壮的Java应用程序至关重要。在处理复杂的数据结构时,应根据需求选择合适的复制策略,以避免不必要的副作用和数据污染。

    Java中的深拷贝(深复制)和浅拷贝(浅复制) 示例代码

    为了理解深拷贝(深复制)和浅拷贝(浅复制),我们需要首先了解Java对象内存的分配方式以及引用的概念。 1. **对象复制的基础** 在Java中,当我们创建一个对象时,系统会在内存中为该对象分配一块空间,存储它的...

    Java中对象的深复制和浅复制详解.doc

    在实际编程中,选择浅复制还是深复制取决于你的需求。如果对象的属性不包含对其他对象的引用,或者你希望修改副本不会影响原始对象,那么浅复制可能是足够的。然而,如果你的对象包含复杂的嵌套结构,或者需要保持...

    android 浅复制和深复制实例

    在Java中,浅复制可以通过实现`Cloneable`接口并覆盖`clone()`方法来完成。 ```java public class Person implements Cloneable { String name; Address address; // ... 构造器、getter和setter等 @Override...

    Java中的深拷贝(深复制)和浅拷贝(浅复制)介绍

    在Java编程语言中,深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是两种不同的对象复制方式,它们涉及到内存中数据的复制和引用的处理。理解这两种拷贝方式对于开发过程中正确管理和操作对象至关重要。 浅拷贝,又...

    java深度复制源代码

    在Java中,对象的复制分为浅复制和深度复制两种。浅复制是指创建一个新的对象,并将原对象的非引用类型的字段值复制到新对象中;对于引用类型的字段,只是复制了引用地址,即新旧对象共享同一份数据。而深度复制则是...

    Java 浅复制和深复制的实例详解

    在本文中,我们介绍了 Java 浅复制和深复制的实例详解,通过代码示例和结果分析,我们可以看到浅复制和深复制的区别和应用场景。浅复制适用于简单的对象复制,而深复制适用于需要完全复制对象的场景。

    Java对象深复制与浅复制实例详解

    Java对象深复制与浅复制是Java编程中两个重要的概念,它们都是对象复制的方式,但它们有着不同的实现机制和应用场景。在本文中,我们将详细介绍Java对象深复制与浅复制的概念、实现机制、应用场景和示例代码。 浅...

    理解java中的深复制和浅复制

    在Java编程中,深复制和浅复制是两个重要的概念,主要涉及到对象的复制与克隆。这两个术语在处理对象的拷贝时具有不同的含义,理解它们对于编写高效且无误的代码至关重要。 首先,让我们来看一下浅复制(Shallow ...

    java不同对象之间及集合的复制

    在Java中,如果类的属性都是基本类型,可以通过构造函数或克隆方法实现浅复制。但如果属性包含引用类型,就需要深复制以确保新对象拥有独立的引用。 3. **注解实现复制**: 注解是一种元数据,可以提供编译时或运行...

    JAVA浅克隆与深克隆

    在Java编程语言中,克隆是创建一个对象副本的过程,这个副本与原对象有相同的属性值,但作为不同的对象存在。克隆分为两种主要类型:浅克隆(Shallow Clone)和深克隆(Deep Clone)。这篇博客文章将探讨这两种克隆...

    浅析Java中的深拷贝与浅拷贝

    首先我们看看浅拷贝和深拷贝的定义 浅拷贝:只复制一个对象,对象内部存在的指向其他对象数组或者引用则不复制 深拷贝:对象,对象内部的引用均复制 为了更好的理解它们的区别我们假设有一个对象A,它包含...

    java不同对象及集合的多次复制

    在Java编程中,对象复制是一项常见的任务,特别是在处理模型(Model)和视图对象(VO)时。模型对象通常用于封装业务数据,而视图对象则用于展示这些数据。值复制,即对象属性值的复制,是保持数据一致性和简化代码...

    java 深克隆浅克隆

    在Java编程语言中,克隆是一种创建对象副本的方法,它允许我们复制一个对象并拥有一个完全独立的新实例,而不是仅仅引用原始对象。克隆技术在处理复杂数据结构、避免对象共享以及实现对象复制等方面有着广泛的应用。...

Global site tag (gtag.js) - Google Analytics