`
阿Q乱七八糟
  • 浏览: 10507 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

java深浅克隆

 
阅读更多

1.首先理解下浅克隆和深克隆的含义吧:

浅克隆:简单说就是对当前要克隆的对象的复制,但是不会复制当前对象对其他对象的引用,即引用还是指向之前被引用对象的地址。

深克隆:就是把要克隆对象以及他所有引用对象全部复制一份。

2.浅克隆的代码演示:通过这段代码你就会明白浅克隆到底是什么意思了。

class Teacher{
	public String name;
	public int age;
	public Teacher(String name,int age){
		this.name = name;
		this.age = age;
	}
}
class Student implements Cloneable{
	public String name;
	public int age;
	public Teacher teacher;
	public Student(String name,int age,Teacher t){
		this.name = name;
		this.age = age;
		this.teacher = t;
	}
	
	@Override
	public Student clone() throws CloneNotSupportedException {
		Student s= (Student)super.clone();
		return s;
	}
}
public class TestClone {
	public static void main(String[] args) throws Exception {
		Teacher teacher = new Teacher("Job",50);
		Student stu1 = new Student("Kobe",24,teacher);
		Student stu2 =  stu1.clone();
		System.out.println("stu1 == stu2?-->" + (stu1 == stu2));
		System.out.println("stu1[name = "+ stu1.name + ",age = " + stu1.age 
				+ "],stu2[name = " + stu2.name + ",age = " + stu2.age + "]");
		System.out.println("stu1.teacher == stu2.teacher?-->" 
				+ (stu1.teacher == stu2.teacher));
		/**
		 * 此处改变stu2引用对象的值,会改变stu1引用对象的值
		 * 
		 */
		stu2.teacher.name = "Mike";
		stu2.teacher.age = 60;
		System.out.println("stu1[name = " + stu1.teacher.name 
				+ ",age = " + stu1.teacher.age + "]");
	}
}

 

由上段代码的结果可以看出:stu1和stu2的内存地址不同,只是形成了值得拷贝,Student对象中的Teacher对象的引用没有改变。一旦改变stu2引用Teacher的值,stu1所引用的Teacher的值也会改变,其实他俩指向的是同一内存地址,这就是所谓的浅克隆。

顺便说一下Object基类中clone()方法的含义:Object中的clone()方法可以识别出我们要复制的是哪一个对象,然后会为此对象分配内存空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。

 引用下官网API的一段话:

The method clone for class Object performs a specific cloning operation. First, if the class of this object does not implement the interface Cloneable, then a CloneNotSupportedException is thrown. Note that all arrays are considered to implement the interface Cloneable. Otherwise, this method creates a new instance of the class of this object and initializes all its fields with exactly the contents of the corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned. Thus, this method performs a "shallow copy" of this object, not a "deep copy" operation.

 

3.深克隆代码的演示:

先来一段代码:

 

class Teacher implements Cloneable{
	public String name;
	public int age;
	public Teacher(String name,int age){
		this.name = name;
		this.age = age;
	}
	@Override
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}
class Student implements Cloneable{
	public String name;
	public int age;
	public Teacher teacher;
	public Student(String name,int age,Teacher t){
		this.name = name;
		this.age = age;
		this.teacher = t;
	}
	
	@Override
	public Student clone() throws CloneNotSupportedException {
		Student s= (Student)super.clone();
		s.teacher = (Teacher)teacher.clone();
		return s;
	}
}
public class TestClone {
	public static void main(String[] args) throws Exception {
		Teacher teacher = new Teacher("Job",50);
		Student stu1 = new Student("Kobe",24,teacher);
		Student stu2 =  stu1.clone();
		System.out.println("stu1 == stu2?-->" + (stu1 == stu2));
		System.out.println("stu1[name = "+ stu1.name + ",age = " + stu1.age 
				+ "],stu2[name = " + stu2.name + ",age = " + stu2.age + "]");
		System.out.println("stu1.teacher == stu2.teacher?-->" 
				+ (stu1.teacher == stu2.teacher));
		/**
		 * 此处改变stu2引用对象的值,不会改变stu1引用对象的值,因为在Student的clone()方法中已经对引用Teacher进行了复制。
		 * 
		 */
		stu2.teacher.name = "Mike";
		stu2.teacher.age = 60;
		System.out.println("stu1[name = " + stu1.teacher.name 
				+ ",age = " + stu1.teacher.age + "]");
	}
}


 

从结果可以看出改变stu2引用对象属性的值,stu1中的引用对象属性值并没有改变,这在要拷贝对象中引用对象内部没有其他引用的时候是成立的,如果Teacher中有其他对象的引用,则这样又会产生浅克隆的现象,这样并不能叫做深克隆,除非一层层的拷贝下去,所以网上很多举例解释是错误的。

 

还有一种是通过串行化来进行深拷贝,也就是流的过程。把对象写入流--->串行化,从流中读出对象--->并行化,对象本身还是存在于JVM中,流也是对对象的一种拷贝。代码如下:

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

class Teacher implements Serializable{
	private static final long serialVersionUID = 1L;
	public String name;
	public int age;
	public Teacher(String name,int age){
		this.name = name;
		this.age = age;
	}
}
class Student implements Serializable{
	private static final long serialVersionUID = 1L;
	public String name;
	public int age;
	public Teacher teacher;
	public Student(String name,int age,Teacher t){
		this.name = name;
		this.age = age;
		this.teacher = t;
	}
	public Object deepClone()throws Exception{
		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());
	}
}
public class TestClone {
	public static void main(String[] args) throws Exception {
		Teacher teacher = new Teacher("Job",50);
		Student stu1 = new Student("Kobe",24,teacher);
		Student stu2 =  (Student)stu1.deepClone();
		System.out.println("stu1 == stu2?-->" + (stu1 == stu2));
		System.out.println("stu1[name = "+ stu1.name + ",age = " + stu1.age 
				+ "],stu2[name = " + stu2.name + ",age = " + stu2.age + "]");
		System.out.println("stu1.teacher == stu2.teacher?-->" 
				+ (stu1.teacher == stu2.teacher));
		/**
		 * 此处改变stu2引用对象的值,不会改变stu1引用对象的值
		 * 
		 */
		stu2.teacher.name = "Mike";
		stu2.teacher.age = 60;
		System.out.println("stu1[name = " + stu1.teacher.name 
				+ ",age = " + stu1.teacher.age + "]");
	}
}

 

从结果可以看出改变stu2引用对象属性的值,stu1中的引用对象属性值并没有改变,这种方法也可以实现深拷贝(前提是所有引用对象都必须可序列化,否则,就需要仔细考察那些不可串行化的对象可否设成transient,从而将之排除在复制过程之外)

 

ok,深浅克隆到此结束,可以下班回家了,吼吼

 

 

  • 大小: 35.5 KB
  • 大小: 35.9 KB
  • 大小: 35.9 KB
分享到:
评论

相关推荐

    Java深浅clone

    总结来说,Java的深浅克隆是对象复制的重要手段。浅克隆适用于字段不包含可变对象或者对象的深层结构不需要独立的情况,而深克隆则在需要完整复制对象及其嵌套对象时更为适用。理解并正确使用这两种克隆方式对于编写...

    JAVA面试宝典.pdf

    clone方法的使用也是面试常考点,涉及对象复制与深浅拷贝的区别。 第三章JavaSE高级,可能涵盖异常处理、多线程、反射、集合框架等主题,这些都是Java程序员进阶必备的知识。 第四章JavaWEB基础,会涉及到Servlet...

    更新至2020年12月最全Java 面试全解析:核心知识点与典型面试题.pdf

    关于类和克隆,主要讨论了克隆的深浅本质。数据结构和队列部分,则不仅深入讲解了集合的使用和关系,还包括队列内容的掌握。 在反射和动态代理部分,重点讲解了反射与动态代理的关系,提供了实际应用场景以及实现...

    JAVA 重点 难点集锦

    3. 构造器:掌握构造器的作用,深浅拷贝的概念,以及构造器的重载。 4. 泛型:泛型提供了一种在编译时检查类型安全的方式,了解其使用规则和好处。 三、异常处理 1. 异常分类:Java异常分为检查型异常和运行时...

    java 水波荡漾的效果

    3. **渲染**:使用Java2D在画布上绘制水面,颜色深浅表示高度差,形成波纹的视觉效果。 4. **更新和重绘**:在每一帧,更新数组中的高度,然后清除画布并重新绘制新的水面状态。 5. **循环播放**:通过`javax.swing....

    Java基础知识点 - 内容比较全面

    深浅拷贝的概念在数组复制时也会涉及,浅拷贝只复制引用,深拷贝复制整个对象及其内容。 这些知识点构成了Java开发者必备的基础,深入理解它们有助于编写出高效、稳定的代码。在实际开发中,还需要结合设计模式、...

    1.深浅拷贝.pptx

    深浅拷贝 深浅拷贝是 JavaScript 中一种常用的数据拷贝方式,分为浅拷贝和深拷贝两种。浅拷贝是指复制对象的引用,而不是复制对象本身,而深拷贝是指完全复制对象。 浅拷贝 浅拷贝是指复制对象的引用,而不是复制...

    08_26_C++ 深浅拷贝的区别

    08_26_C++ 深浅拷贝的区别08_26_C++ 深浅拷贝的区别08_26_C++ 深浅拷贝的区别08_26_C++ 深浅拷贝的区别08_26_C++ 深浅拷贝的区别08_26_C++ 深浅拷贝的区别08_26_C++ 深浅拷贝的区别08_26_C++ 深浅拷贝的区别08_26_...

    ios中深浅拷贝的讲解

    ios中深浅拷贝的讲解,通俗移动。深浅拷贝是ios开发人员面试经常会被问到的知识点,看了本文档,相信你回答ios中的深浅拷贝有不一样的认识。

    Swift5 iOS深浅模式适配

    swift5 Demo,Xcode11创建项目,并且支持iOS13以下版本,支持iOS13深浅模式图片以及颜色动态变化。 使用SnapKit 5.0约束框架,Alamofire 5.0最新版本网络请求。 项目为标准的UITabBarController布局,项目下载修改...

    将图片转换为springbanner文本资源的工具_java_代码_下载

    接着,根据像素的颜色深浅将其转换为不同字符,通常会使用ASCII字符集中的字符来近似表示原图的色彩和形状。此过程可能涉及到对颜色的阈值处理,以确定哪些颜色应转换为哪种字符。 在转换过程中,工具可能会使用...

    PD4ML 实测Java将HTML导出为PDF 成功解决中文乱码问题

    本篇将深入探讨如何使用PD4ML实现在Java环境中处理中文乱码问题,并提供相关文件的背景和用途。 首先,我们要理解为何会出现中文乱码。在处理非ASCII字符,如中文字符时,如果字体、编码设置不正确,就可能出现乱码...

    c python java 复制数组 深浅拷贝

    在不同的语言中,如C、Python和Java,数组复制有深拷贝和浅拷贝两种方式,它们之间的区别在于是否拷贝了底层的数据结构。 在Java中,数组的复制可以通过简单的赋值操作实现,例如`int[] a2 = a1;`。这种方式被称为...

    iOS深浅拷贝例子

    在iOS开发中,深拷贝和浅拷贝是两个重要的概念,主要涉及到对象复制时内存管理的问题。这两个术语经常在讨论Objective-C中的`NSCopying`和`NSMutableCopying`协议时出现,以及Swift中的`Copyable`和`MutableCopyable...

    java算法大全

    另外,书中的数学深浅适中,足够使你了解并分析算法的性能。 通过本书,你可以: · 解决特定代码的问题,或者提升现有解决方案的性能。 · 快速找到与你所解决的问题相关的算法,并决定哪种算法才是最适合的。 ·...

    Arthas开源Java诊断工具包

    颜色的深浅通常与执行时间或频率有关,颜色越深,表示执行频率越高或者耗时越长。通过这种方式,我们可以看到哪些代码片段是性能的“热点”,并据此进行优化。 Arthas的`profile`命令使用非常灵活,可以针对特定的...

    Java例题第三章_java_mannerp82_

    在本Java学习资源中,我们聚焦于第三章的例题,涵盖了面向对象编程的重要概念,包括类的继承、封装、对象数组操作以及深浅拷贝等。这些例题旨在帮助初学者深入理解Java编程的核心机制。 首先,让我们讨论"例03.01 ...

    面向对象的程序设计与java课件

    此外,还会涉及对象的引用和深浅拷贝。 6、字符串:字符串在Java中是重要的数据结构,会介绍String类的常用方法,如拼接、查找、替换和截取等。 7、数组:讲解数组的概念,包括一维数组和多维数组的声明、初始化、...

Global site tag (gtag.js) - Google Analytics