`

Cloneable

阅读更多
clone
一、应用场景
  • 循环遍历,循环中创建新的对象
  • 设计模式 -- 原型模式



二、总结

1.浅拷贝与深拷贝

调用 object.clone 方法,即浅拷贝;
浅拷贝:原对象中的属性 与 拷贝对象中的属相指向了堆中同一个对象的
重写 object.clone 方法,对引用数据类型,进行 显示的clone 声明
深拷贝:对象中的属性值也进行了相应的拷贝

2.拷贝的彻底性

Class A 中 对 Class B 进行引用
Class B 中 对 Class C 进行引用

在 A 中进行深拷贝,仅仅是对 B 进行了拷贝,而未对 C 进行处理;所以 C 依然是浅拷贝

3.clone 与 new 的区别联系

new 在堆中开辟新的空间,并调用构造方法进行初始化,返回一个地址引用
clone 同样开辟新的空间,区别在于新的空间中的引用数据类型是否与原来的对象共用一个引用地址;所以才有深浅拷贝的区分

三、示例解释

1.基本数据类型与引用数据类型String

package com.java.study.test.unit1;

public class Person implements Cloneable {

	private int age ;
	private String name ;
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Person(int age, String name) {
		super();
		this.age = age;
		this.name = name;
	}
	
	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}

public class PersonMain {

	/**
	 * @param args
	 * @throws CloneNotSupportedException 
	 */
	public static void main(String[] args) throws CloneNotSupportedException {
		
		Person person = new Person(1,"1");
		Person personClone = (Person) person.clone();
		
		// 基本数据类型:深拷贝,原对象的数据变更,不影响拷贝后的对象中的属性的值
		person.setAge(2);
		System.out.println(personClone.getAge());
		// 引用数据类型:若在clone 中未显示声明克隆,则为浅拷贝,原对象中属性的改变影响新对象的值
		// String 特殊:String 对象的不可变性,克隆的同时 personClone.name 生成了新的字符串对象,并将新对象的地址返回
		// 即:不是深拷贝导致原对象与拷贝对象中的属性的地址不一致;而是String的不可变的特性
		person.setName("2");
		System.out.println(personClone.getName()); // 输出 1
                // 如果Stirng 是浅拷贝,原对象与拷贝对象中的name属性指向堆中同一地址,原对象属性的改变会对克隆对象产生影响 
		System.out.println(person.getName() == personClone.getName());
	}




结论:
基本数据类型是深拷贝
引用类型的String是特例,浅拷贝,最终的效果是深拷贝,原对象与克隆对象不共享属性在堆中的地址

2.引用数据类型
package com.java.study.test.unit1;

public class Person implements Cloneable {

	private int age ;
	private String name ;
	private Friend friend ;
	
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Person(int age, String name) {
		super();
		this.age = age;
		this.name = name;
	}
	
	public Friend getFriend() {
		return friend;
	}
	public void setFriend(Friend friend) {
		this.friend = friend;
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}






package com.java.study.test.unit1;

public class Friend {

	private String gender ;

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public Friend(String gender) {
		super();
		this.gender = gender;
	}
	
	
}



	public static void main(String[] args) throws CloneNotSupportedException {
		
		Person person = new Person(1,"1");
		Friend friend = new Friend("male");
		person.setFriend(friend);
		Person personClone = (Person) person.clone();
                // 输出 male 
		System.out.println(personClone.getFriend().getGender());
		// 输出 female 
                // 说明引用数据类型默认为浅拷贝;共同指向堆中的同一地址
		person.getFriend().setGender("female");
		System.out.println(personClone.getFriend().getGender());
      }


结论:引用数据类型默认为浅拷贝

3.
package com.java.study.test.unit1;

public class Person implements Cloneable {

	private int age ;
	private String name ;
	private Friend friend ;
	
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Person(int age, String name) {
		super();
		this.age = age;
		this.name = name;
	}
	
	public Friend getFriend() {
		return friend;
	}
	public void setFriend(Friend friend) {
		this.friend = friend;
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Person p = (Person) super.clone();
		p.friend = (Friend) friend.clone();
		return p;
	}
}







package com.java.study.test.unit1;

public class Friend implements Cloneable{

	private String gender ;

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public Friend(String gender) {
		super();
		this.gender = gender;
	}
	
	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}


结论:深拷贝即对类中的每一个引用数据逐一进行克隆

4.泛型


	public static void main(String[] args) throws CloneNotSupportedException {
		
		Person person = new Person(1,"1");
		Person person1 = new Person(2,"2");
		ArrayList<Person> list = new ArrayList<Person>(2);
		list.add(person);
		list.add(person1);
		@SuppressWarnings("unchecked")
		ArrayList<Person> copyList = (ArrayList<Person>) list.clone();
		for(Person personCopy : copyList){
			System.out.println("index:"+personCopy.getAge()+",name:"+personCopy.getName());
		}
		// 浅拷贝
//		person.setName("5");
//		person1.setName("6");
//		for(Person personCopy : copyList){
//			System.out.println("index:"+personCopy.getAge()+",name:"+personCopy.getName());
//		}
		// 深拷贝:遍历集合,对集合中的每一个对象进行拷贝处理
		ArrayList<Person> newCopyList = new ArrayList<Person>(2);
		for(int index = 0 ; index < list.size() ; index ++){
			newCopyList.add((Person) list.get(index).clone());
		}
		person.setName("5");
		person1.setName("6");
		for(Person personCopy : newCopyList){
			System.out.println("index:"+personCopy.getAge()+",name:"+personCopy.getName());
		}
}


结论:泛型中的拷贝,要遍历泛型对每一个对象进行克隆


四、参考博客

详解Java中的clone方法 -- 原型模式

使用序列化实现对象的拷贝

分享到:
评论

相关推荐

    day16-Map、可变参数、Cloneable.pdf

    总的来说,Map接口提供了一种高效的方式来存储和检索键值对数据,可变参数简化了函数调用,Cloneable接口支持对象的克隆,而多线程则为并发编程提供了基础。理解和掌握这些知识点对于Java开发至关重要。

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

    安装可克隆您应该安装 : Install-Package Cloneable或者通过 .NET Core 命令行界面: dotnet add package Cloneable来自包管理器控制台或 .NET Core CLI 的任一命令都将下载并安装 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 . ...

    deep_cloneable:这个宝石给每一个ActiveRecord

    deep_cloneable 这个gem为每个ActiveRecord :: Base对象提供了进行深度克隆的可能性,该克隆包括用户指定的关联。 这是的Rails 3+升级。要求Ruby 1.9.3、2.0.0、2.1.5、2.2.2、2.3.0、2.4.4、2.5.5、2.6.3(已测试)...

    U10316024_HW_15_10:类 MyStack 实现 Cloneable 并使用深循环

    在本题目中,我们面临的是一个关于 Java 编程的任务,目标是实现一个名为 `MyStack` 的类,该类需要实现 `Cloneable` 接口,并且支持深拷贝功能。深拷贝是一种复制对象的方式,它不仅复制对象本身,还复制对象引用的...

    2019年最新版修订版Java程序员面试宝典.pdf

    3. **克隆对象**:Java中可以通过实现`Cloneable`接口并重写`clone()`方法来实现对象的浅拷贝。如果想要实现深拷贝,则需要更复杂的方法。 ##### 二、JavaSE语法 1. **Java的`goto`语句**:Java中不支持`goto`语句...

    01-02-02-原型模式详解1

    `Cloneable`接口是用于标记对象可以被克隆,而`Serializable`接口则是用于对象的序列化和反序列化,但这通常用于跨网络传输或持久化存储,而不是直接的克隆。 首先,让我们看看如何使用`Cloneable`接口来实现原型...

    学习Java实验7抽象类和接口.pdf

    本实验主要讲解了Java中的抽象类和接口的概念和使用方法,并且深入探讨了 Cloneable 接口和 clone 方法在对象内容复制中的应用。 一、抽象类的概念和使用方法 在 Java 中,抽象类是一个不能被实例化的类,它提供了...

    Java深浅clone

    在Java编程语言中,`Cloneable`接口和`clone()`方法是两个重要的概念,它们用于对象复制。在本文中,我们将深入探讨Java中的浅克隆(shallow clone)和深克隆(deep clone),并结合测试代码进行分析。 首先,让...

    java对象复制.pdf

    3. 处理`CloneNotSupportedException`:尽管我们的类实现了`Cloneable`,但在某些情况下,如父类未实现`Cloneable`时,仍然可能会抛出异常,因此需要捕获并处理它。 当一个对象被`clone()`时,如果对象内部含有其他...

    java 原型模式

    这种模式的核心在于Java中的`Cloneable`接口和`clone()`方法。 首先,我们要了解`Cloneable`接口。在Java中,如果一个类想要实现克隆功能,必须实现`Cloneable`接口。这个接口没有定义任何方法,仅仅是一个标记接口...

    JAVA_对象克隆

    1. 实现`Cloneable`接口:为了让对象可以被克隆,首先需要在类声明中添加`implements Cloneable`。 2. 覆盖`clone()`方法:重写`clone()`方法,通常只需返回`super.clone()`,但要注意处理可能抛出的`...

    编程语言java对象复制.pdf

    在给出的内容部分中,通过具体的Java代码示例,讨论了在Java中实现对象复制的机制,特别是通过实现Cloneable接口和重写Object类的clone方法来完成对象的浅复制与深复制。 知识点一:Java对象复制的基本概念 在Java...

    原型模式代码示例

    在Java中,我们可以利用`java.lang.Cloneable`接口和`clone()`方法来实现原型模式。 在Java中,实现原型模式主要有两个步骤: 1. **实现Cloneable接口**:首先,我们需要让我们的类实现`Cloneable`接口。这个接口...

    java深度克隆

    ### Java深度克隆详解 #### 一、引言 在Java开发过程中,对象拷贝是一项常见操作。...无论是使用`Cloneable`接口还是序列化与反序列化,深度克隆都能有效地解决对象拷贝带来的问题,提高程序的稳定性和安全性。

    java深复制

    2. **使用`Cloneable`接口和`clone()`方法**:Java提供了一个`Cloneable`接口,当一个类实现了这个接口,它的实例就可以被克隆。但是,`Object`类的`clone()`方法默认执行的是浅复制。为了实现深复制,我们需要在...

    Java实验7抽象类和接口.pdf

    抽象类和接口 ...通过这个实验,我们学习了抽象类、接口、Cloneable 接口和多态性的概念,并掌握了如何使用它们来编写 Java 程序。我们还学习了浅拷贝和深拷贝的概念,并掌握了如何消除浅拷贝的方法。

    Java原型模式

    在Java中,原型模式通过实现Cloneable接口和覆盖clone()方法来复制对象,避免了使用构造函数进行深度复制的复杂性。接下来我们将深入探讨Java原型模式的核心概念、实现方式以及实际应用。 ### 核心概念 1. **原型...

    Java Clone(类的复制)实例代码

    在Java中,如果一个类想要实现`clone()`方法,必须实现`Cloneable`接口。如果不这样做,Java会抛出`CloneNotSupportedException`异常。`Cloneable`接口本身没有定义任何方法,它的作用就是标记一个类为可克隆的。 ...

    JAVA上机实验报告.docx

    实验要求学生设计并实现一个名为`Octagon`的类,该类继承自`GeometricObject`抽象类,并实现了`Comparable`和`Cloneable`接口。通过此类的设计与实现,学生将能够更加熟练地运用面向对象编程的原则和技术来解决问题...

Global site tag (gtag.js) - Google Analytics