广告
返回顶部
首页 > 资讯 > 前端开发 > VUE >什么是Java浅拷贝和深拷贝
  • 295
分享到

什么是Java浅拷贝和深拷贝

2024-04-02 19:04:59 295人浏览 八月长安
摘要

这篇文章主要讲解了“什么是Java浅拷贝和深拷贝”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“什么是Java浅拷贝和深拷贝”吧!问题“如果你有一个对象, 并

这篇文章主要讲解了“什么是Java浅拷贝和深拷贝”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“什么是Java浅拷贝和深拷贝”吧!

问题

“如果你有一个对象, 并希望生成与其完全相同的一个复制品, 你该如何实现呢?首先, 你必须新建一个属于相同类的对象。然后,  你必须遍历原始对象的所有成员变量, 并将成员变量值复制到新对象中。

for (int i = 0; i < 10; i++) {   Sheep sheep = new Sheep("肖恩"+i+"号",2+i,"白色");   System.out.println(sheep.toString()); }

这种方式是比较容易想到的,但是有几个不足

  • 在创建新对象的时候,总是需要重新获取原始对象的属性,如果创建的对象比较复杂,效率会很低

  • 总是需要重新初始化对象,而不是动态地获得对象运行时的状态, 不够灵活

  • 另一方面,并非所有对象都能通过这种方式进行复制, 因为有些对象可能拥有私有成员变量, 它们在对象本身以外是不可见的

“万物兼对象的 Java 中的所有类的根类 Object,提供了一个 clone() 方法,该方法可以将一个 Java 对象复制一份,但是需要实现  clone() 的类必须要实现一个接口 Cloneable,该接口表示该类能够复制且具有复制的能力。这就引出了原型模式。

基本介绍

  1. 原型模式(Prototype模式)是指:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象

  2. 原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类

  3. 工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建,即  对象**.clone**()

类图

什么是Java浅拷贝和深拷贝

  • Prototype : 原型 (Prototype) 接口将对克隆方法进行声明

Java 中 Prototype 类需要具备以下两个条件

  1. 实现 Cloneable 接口。在 Java 语言有一个 Cloneable  接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用 clone 方法。在 Java  虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出 CloneNotSupportedException 异常

  2. 重写 Object 类中的 clone 方法。Java 中,所有类的父类都是 Object 类,Object 类中有一个 clone  方法,作用是返回对象的一个拷贝

  • ConcretePrototype:具体原型 (Concrete Prototype) 类将实现克隆方法。除了将原始对象的数据复制到克隆体中之外,  该方法有时还需处理克隆过程中的极端情况, 例如克隆关联对象和梳理递归依赖等等。

  • Client: 使用原型的客户端,首先要获取到原型实例对象,然后通过原型实例克隆自己,从而创建一个新的对象。

实例

“我们用王二小放羊的例子写这个实例

1、原型类(实现 Clonable)

@Setter @Getter @NoArgsConstructor @AllArgsConstructor class Sheep implements Cloneable {     private String name;     private Integer age;     private String color;      @Override     protected Sheep clone() {         Sheep sheep = null;         try {             sheep = (Sheep) super.clone();         } catch (Exception e) {             System.out.println(e.getMessage());         }         return sheep;     } }

2、具体原型

按业务的不同实现不同的原型对象,假设现在主角是王二小,羊群里有山羊、绵羊一大群

public class Goat extends Sheep{     public void graze() {         System.out.println("山羊去吃草");     } }
public class Lamb extends Sheep{     public void graze() {         System.out.println("羔羊去吃草");     } }

3、客户端

public class Client {      static List<Sheep> sheepList = new ArrayList<>();     public static void main(String[] args) {         Goat goat = new Goat();         goat.setName("山羊");         goat.setAge(3);         goat.setColor("灰色");         for (int i = 0; i < 5; i++) {             sheepList.add(goat.clone());         }          Lamb lamb = new Lamb();         lamb.setName("羔羊");         lamb.setAge(2);         lamb.setColor("白色");         for (int i = 0; i < 5; i++) {             sheepList.add(lamb.clone());             System.out.println(lamb.hashCode()+","+lamb.clone().hashCode());         }          for (Sheep sheep : sheepList) {             System.out.println(sheep.toString());         } }

原型模式将克隆过程委派给被克隆的实际对象。模式为所有支持克隆的对象声明了一个通用接口,  该接口让你能够克隆对象,同时又无需将代码和对象所属类耦合。通常情况下,这样的接口中仅包含一个 克隆方法。

所有的类对 克隆方法的实现都非常相似。该方法会创建一个当前类的对象, 然后将原始对象所有的成员变量值复制到新建的类中。你甚至可以复制私有成员变量,  因为绝大部分编程语言都允许对象访问其同类对象的私有成员变量。

支持克隆的对象即为原型。当你的对象有几十个成员变量和几百种类型时, 对其进行克隆甚至可以代替子类的构造。

优势

使用原型模式创建对象比直接 new 一个对象在性能上要好的多,因为 Object 类的 clone  方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。

使用原型模式的另一个好处是简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。

因为以上优点,所以在需要重复地创建相似对象时可以考虑使用原型模式。比如需要在一个循环体内创建对象,假如对象创建过程比较复杂或者循环次数很多的话,使用原型模式不但可以简化创建过程,而且可以使系统的整体性能提高很多。

适用场景

《Head First 设计模式》是这么形容原型模式的:当创建给定类的实例的过程很昂贵或很复杂时,就是用原型模式。

如果你需要复制一些对象,同时又希望代码独立于这些对象所属的具体类,可以使用原型模式。

如果子类的区别仅在于其对象的初始化方式, 那么你可以使用该模式来减少子类的数量。别人创建这些子类的目的可能是为了创建特定类型的对象

原型模式在 Spring 中的应用

我们都知道 spring bean 默认是单例的,但是有些场景可能需要原型范围,如下

<bean id="sheep" class="priv.starfish.prototype.Sheep" scope="prototype">    <property name="name" value="肖恩"/>    <property name="age" value="2"/>    <property name="color" value="白色"/> </bean>

同样,王二小还是有 10 只羊,感兴趣的也可以看下他们创建的对象是不是同一个

public class Client {     public static void main(String[] args) {         ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");         for (int i = 0; i < 10; i++) {             Object bean = context.getBean("sheep");             System.out.println(bean);         }     } }

感兴趣的同学可以深入源码看下具体的实现,在 AbstractBeanFactory 的 doGetBean() 方法中

什么是Java浅拷贝和深拷贝

原型模式的注意事项

  • 使用原型模式复制对象不会调用类的构造方法。因为对象的复制是通过调用 Object 类的 clone  方法来完成的,它直接在内存中复制数据,因此不会调用到类的构造方法。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。还记得单例模式吗?单例模式中,只要将构造方法的访问权限设置为  private 型,就可以实现单例。但是 clone 方法直接无视构造方法的权限,所以,单例模式与原型模式是冲突的,在使用时要特别注意。

  • 深拷贝与浅拷贝。Object 类的  clone方法只会拷贝对象中的基本的数据类型,对于数组容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。

浅拷贝和深拷贝

首先需要明白,浅拷贝和深拷贝都是针对一个已有对象的操作。

在 Java 中,除了基本数据类型(元类型)之外,还存在 类的实例对象 这个引用数据类型。而一般使用 『 =  』号做赋值操作的时候。对于基本数据类型,实际上是拷贝的它的值,但是对于对象而言,其实赋值的只是这个对象的引用,将原对象的引用传递过去,他们实际上还是指向的同一个对象。

而浅拷贝和深拷贝就是在这个基础之上做的区分,如果在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用数据类型只是进行了引用的传递,而没有真实的创建一个新的对象,则认为是浅拷贝。反之,在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量,则认为是深拷贝。

“所谓的浅拷贝和深拷贝,只是在拷贝对象的时候,对 类的实例对象 这种引用数据类型的不同操作而已

浅拷贝

  1. 对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。

  2. 对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值

  3. 前面我们克隆羊就是浅拷贝,如果我们在 Sheep 中加一个对象类型的属性,public Sheep child;可以看到 s 和 s1 的 friend  是同一个。

 Sheep s = new Sheep();   s.setName("sss");      s.friend = new Sheep();   s.friend.setName("喜洋洋");      Sheep s1 = s.clone();   System.out.println(s == s1);   System.out.println(s.hashCode()+"---"+s.clone().hashCode());      System.out.println(s.friend == s1.friend);   System.out.println(s.friend.hashCode() + "---" +s1.friend.hashCode()); false 621009875---1265094477 true 2125039532---2125039532

深拷贝

现在我们知道 clone() 方法,只能对当前对象进行浅拷贝,引用类型依然是在传递引用。那如何进行一个深拷贝呢?

常见的深拷贝实现方式有两种:

  1. 重写 clone 方法来实现深拷贝

  2. 通过对象序列化实现深拷贝

浅拷贝和深拷贝只是相对的,如果一个对象内部只有基本数据类型,那用 clone() 方法获取到的就是这个对象的深拷贝,而如果其内部还有引用数据类型,那用  clone() 方法就是一次浅拷贝的操作。

感谢各位的阅读,以上就是“什么是Java浅拷贝和深拷贝”的内容了,经过本文的学习后,相信大家对什么是Java浅拷贝和深拷贝这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: 什么是Java浅拷贝和深拷贝

本文链接: https://www.lsjlt.com/news/84780.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 什么是Java浅拷贝和深拷贝
    这篇文章主要讲解了“什么是Java浅拷贝和深拷贝”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“什么是Java浅拷贝和深拷贝”吧!问题“如果你有一个对象, 并...
    99+
    2022-10-19
  • 什么是深拷贝和浅拷贝
    深拷贝和浅拷贝分别是指:深拷贝是指拷贝对象的具体内容,二内存地址是自主分配的,拷贝结束之后俩个对象虽然存的值是一样的,但是内存地址不一样,俩个对象页互相不影响,互不干涉。浅拷贝是指对内存地址的复制,让目标对象指针和源对象指向同一片内存空间。...
    99+
    2023-10-29
  • 浅拷贝&深拷贝
    浅拷贝新的对象指向原来对象的地址 深拷贝新的对象中,原来是可变对象,会新复制一份值指向新的地址[11,22,33]若原来的对象里含有可变对象,里面的这个可变对象也会指向新的地址['qwer', 123, [44,55]] 参考:https...
    99+
    2023-01-30
  • python浅拷贝和深拷贝
    python中的赋值是按引用来传递的,如果不是赋值而是拷贝,那就需要用到copy模块了,这就不得不谈浅拷贝和深拷贝了。   浅拷贝copy()   #!/usr/bin/python  import copy  class MyClass:...
    99+
    2023-01-31
    和深 python
  • java对象拷贝之深拷贝与浅拷贝
    要实现对象拷贝必须实现一个Cloneable接口,如果不实现这个接口就会产生一个CloneNotSupportedException异常。其实这个接口一个方法都没有,因此这类接口常被称作标记接口。Object 中有一个clone() 方法实...
    99+
    2016-12-31
    java入门 java 对象 深拷贝 浅拷贝
  • JavaScript深拷贝与浅拷贝是什么
    这篇文章主要介绍了JavaScript深拷贝与浅拷贝是什么,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1 浅拷贝概念深拷贝和浅拷贝是只针对Object和Array这样的引用...
    99+
    2023-06-29
  • 浅拷贝与深拷贝
       名词解释 1.对象:被分配的一块内存,存储其所代表的值 2.引用:是自动形成的从变量到对象的指针 3.注意:类型(int类型,long类型(python3已去除long类型,只剩下int类型的数据))属于对象,不是变量 4.不可变...
    99+
    2023-01-30
  • python深拷贝浅拷贝
    python深拷贝和浅拷贝问题:   什么是深拷贝?     (个人理解)深拷贝就是将原有的数据一模一样的拷贝一份,然后存到另一个地址中,而不是引用地址   什么是浅拷贝?     (个人理解)就是引用地址 (1)用等于号的拷贝都属于浅拷...
    99+
    2023-01-30
    python
  • 浅谈JavaScript浅拷贝和深拷贝
    目录一、直接赋值二、浅拷贝三、深拷贝1. JSON对象的方式2. 递归复制网上关于这个话题,讨论有很多了,根据各路情况我自己整理了一下,最后还是能接近完美的实现深拷贝,欢迎大家讨论。...
    99+
    2022-11-12
  • 在java中深拷贝和浅拷贝区别是什么
    在java中深拷贝和浅拷贝区别:浅拷贝是指向被复制的内存地址,而深拷贝是创建新的内存地址用于存放复制的对象。浅拷贝对于引用类型的属性只是引用原对象的内存地址,而深拷贝是所有属性都创建新的对象。...
    99+
    2022-10-03
  • Java中的深拷贝和浅拷贝是什么意思
    这篇文章主要讲解了“Java中的深拷贝和浅拷贝是什么意思”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中的深拷贝和浅拷贝是什么意思”吧! 一、前言拷贝这个词想必大家都很熟悉...
    99+
    2023-06-15
  • Java中浅拷贝和深拷贝详解
    目录Java浅拷贝深拷贝实现浅拷贝实现深拷贝Java浅拷贝深拷贝 浅拷贝和深拷贝涉及到了Object类中的clone()方法 实现浅拷贝 浅拷贝的实现需要类重写clone()方法 ...
    99+
    2022-11-12
  • Java深拷贝与浅拷贝的区别是什么
    这篇文章主要介绍“Java深拷贝与浅拷贝的区别是什么”,在日常操作中,相信很多人在Java深拷贝与浅拷贝的区别是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java深拷...
    99+
    2022-10-19
  • java中的浅拷贝与深拷贝
    1、什么叫Java浅拷贝?浅拷贝是会将对象的每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用,当引用指向的值改变时也会跟着变化。2、什么叫Java深拷贝?深拷贝复制变量值,对于引用数据,则递归至基本类型后,再复制。深...
    99+
    2021-10-17
    java教程 java 浅拷贝 深拷贝
  • Java的深拷贝和浅拷贝深入了解
    关于Java的深拷贝和浅拷贝,简单来说就是创建一个和已知对象一模一样的对象。可能日常编码过程中用的不多,但是这是一个面试经常会问的问题,而且了解深拷贝和浅拷贝的原理,对于Java中的...
    99+
    2022-11-13
  • python深拷贝与浅拷贝
    可变对象与不可变对象 要理解深拷贝和浅拷贝,首先要理解可变对象和不可变对象。 不可变对象:该对象所指向的内存中的值不能被改变,修改对象的值时,由于其指向的值不能被改变,因此实际上是在内存中重新开辟一个地址用来存储新的值,然后将对象指向这个...
    99+
    2023-01-30
    python
  • Java的深拷贝和浅拷贝怎么实现
    这篇文章主要介绍“Java的深拷贝和浅拷贝怎么实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java的深拷贝和浅拷贝怎么实现”文章能帮助大家解决问题。关于Java的深拷贝和浅拷贝,简单来说就是创...
    99+
    2023-06-26
  • 浅拷贝和深拷贝的区别
    浅拷贝,指的是重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用。 2、深拷贝,是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任...
    99+
    2023-09-21
    python
  • 分析JavaScript浅拷贝和深拷贝
    本篇内容主要讲解“分析JavaScript浅拷贝和深拷贝”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分析JavaScript浅拷贝和深拷贝”吧!一、直接赋值对象是引用类型,如果直接赋值给另外一...
    99+
    2023-06-25
  • 怎么理解python指针拷贝,浅拷贝和深拷贝
    本篇内容主要讲解“怎么理解python指针拷贝,浅拷贝和深拷贝”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解python指针拷贝,浅拷贝和深拷贝”吧!首先对于不可变类型int,strin...
    99+
    2023-06-02
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作