iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > JAVA >Java基础:对象的克隆(复制)
  • 922
分享到

Java基础:对象的克隆(复制)

数据结构 2023-09-26 08:09:42 922人浏览 泡泡鱼
摘要

假如想复制一个简单变量。很简单: int apples = 5;int pears = apples; 不仅int类型,其它七种原始数据类型(boolean,char,byte,short,float,double.long)同样适用于该类

假如想复制一个简单变量。很简单:

int apples = 5;int pears = apples;

不仅int类型,其它七种原始数据类型(boolean,char,byte,short,float,double.long)同样适用于该类情况。

但是如果你复制的是一个对象,情况就复杂了。

假设说我是一个beginner,我会这样写:

class Student {      private int number;        public int getNumber() {          return number;      }        public void setNumber(int number) {          this.number = number;      }        }  public class Test {      public static void main(String args[]) {          Student stu1 = new Student();          stu1.setNumber(12345);          Student stu2 = stu1;                    System.out.println("学生1:" + stu1.getNumber());          System.out.println("学生2:" + stu2.getNumber());      }  } 

结果:

学生1:12345  

学生2:12345  


这里自定义学生类,该类只有number字段。

我们新建了一个学生实例,然后将该值赋值给stu2实例。(Student stu2 = stu1;)

再看看打印结果,作为一个新手,拍了拍胸腹,对象复制不过如此,

难道真的是这样吗?

我们试着改变stu2实例的number字段,再打印结果看看:

stu2.setNumber(54321);    System.out.println("学生1:" + stu1.getNumber()); // 学生1:54321  System.out.println("学生2:" + stu2.getNumber()); // 学生2:54321  

为什么改变学生2的学号,学生1的学号也发生变化?

原因出在(stu2 = stu1) 这一句。该语句是将stu1的引用赋值给stu2,

这样,stu1和stu2指向内存堆中同一个对象。如图:


那么,怎样才能达到复制一个对象呢?

是否记得万类之王Object。它有11个方法,有两个protected的方法,其中一个为clone方法。

在Java中所有的类都是继承自Java语言包中的Object类的,查看它的源码,发现里面有一个访问限定符为protected的方法clone():

protected native Object clone() throws CloneNotSupportedException;

仔细一看,它还是一个native方法,大家都知道native方法是非Java语言实现的代码,供Java程序调用的,因为Java程序运行在JVM虚拟机上,要想访问比较底层与操作系统相关的就没办法,只能由靠近操作系统的语言来实现。

  1. 第一次声明保证克隆对象将有单独的内存地址分配。
  2. 第二次声明表明,原始和克隆的对象应该具有相同的类类型,但它不是强制性的。
  3. 第三声明表明,原始和克隆的对象应该是平等的equals()方法使用,但它不是强制性的。

因为每个类直接或间接的父类都是Object,因此它们都含有clone()方法,但是因为该方法是protected,所以都不能在类外进行访问。

要想对一个对象进行复制,就需对clone方法覆盖。


为什么要克隆?

为什么需要克隆对象?直接new一个对象不行吗?

答案是:克隆的对象可能包含一些已修改过的属性,而new出来的对象的属性都是初始化时的值,所以当需要一个新的对象来保存当前对象的“状态”就靠clone方法。

那把这个对象的临时属性一个个赋值给新new的对象不也行嘛?可以是可以,但是一来麻烦不说,二来,通过上面的源码都发现clone是一个native方法,就是快,在底层实现。

提个醒,我们常见的Object a=new Object();Object b;b=a;这种形式的代码复制的是引用,即对象在内存中的地址,a和b对象仍指向同一个对象。

而通过clone方法赋值的对象跟原来的对象是同时独立存在的。


如何实现克隆

介绍下两种不同的克隆方法,浅克隆(ShallowClone)深克隆(DeepClone)

Java语言中,数据类型分为值类型(基本数据类型)和引用类型,值类型包括int、double、byte、boolean、char等简单数据类型,引用类型包括类、接口、数组等复杂类型。浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制,下面将对两者进行详细介绍。

一般步骤是(浅克隆):

 被复制的类需实现Clonenable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常), 该接口为标记接口(不含任何方法)

 覆盖clone()方法,访问修饰符设为public方法中调用super.clone()方法得到需要的复制对象。(native为本地方法)

下面对上面那个方法进行改造:

class Student implements Cloneable{      private int number;        public int getNumber() {          return number;      }        public void setNumber(int number) {          this.number = number;      }            @Override      public Object clone() {          Student stu = null;          try{              stu = (Student)super.clone();          }catch(CloneNotSupportedException e) {              e.printStackTrace();          }          return stu;      }  }  public class Test {      public static void main(String args[]) {          Student stu1 = new Student();          stu1.setNumber(12345);          Student stu2 = (Student)stu1.clone();                    System.out.println("学生1:" + stu1.getNumber()); // 学生1:12345          System.out.println("学生2:" + stu2.getNumber()); // 学生2:12345                    stu2.setNumber(54321);                System.out.println("学生1:" + stu1.getNumber()); // 学生1:12345          System.out.println("学生2:" + stu2.getNumber()); // 学生2:54321    }  } 

如果还不相信这两个对象不是同一个对象,可以看看这一句:

System.out.println(stu1 == stu2); // false  

上面被称为浅克隆。

还有一种复杂的深度复制:

我们在学生类里再加一个Address类。

class Address  {    private String add;    public String getAdd() {        return add;    }    public void setAdd(String add) {        this.add = add;    }}class Student implements Cloneable{    private int number;    private Address addr;    public Address getAddr() {        return addr;    }    public void setAddr(Address addr) {        this.addr = addr;    }    public int getNumber() {        return number;    }    public void setNumber(int number) {        this.number = number;    }    @Override    public Object clone() {        Student stu = null;        try{            stu = (Student)super.clone();        }catch(CloneNotSupportedException e) {            e.printStackTrace();        }        return stu;    }}public class Test {    public static void main(String args[]) {        Address addr = new Address();        addr.setAdd("杭州市");        Student stu1 = new Student();        stu1.setNumber(123);        stu1.setAddr(addr);        Student stu2 = (Student)stu1.clone();        System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());        System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());    }}

结果:

学生1:123,地址:杭州市  学生2:123,地址:杭州市

乍一看没问题,真的是这样吗?在main方法中改变addr实例的地址。

addr.setAdd("西湖区");    System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());  System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());  

结果:

学生1:123,地址:杭州市  学生2:123,地址:杭州市  学生1:123,地址:西湖区  学生2:123,地址:西湖区 

这就奇怪了,怎么两个学生的地址都改变了?

原因是浅复制只复制addr变量的引用,并没有真正的开辟另一块空间,将值复制后再将引用返回给新对象。

所以,为了达到真正的复制对象,而不是纯粹引用复制。需要将Address类可复制化,并且修改clone方法,完整代码如下:

class Address implements Cloneable {    private String add;    public String getAdd() {        return add;    }    public void setAdd(String add) {        this.add = add;    }    @Override    public Object clone() {        Address addr = null;        try{            addr = (Address)super.clone();        }catch(CloneNotSupportedException e) {            e.printStackTrace();        }        return addr;    }}class Student implements Cloneable{    private int number;    private Address addr;    public Address getAddr() {        return addr;    }    public void setAddr(Address addr) {        this.addr = addr;    }    public int getNumber() {        return number;    }    public void setNumber(int number) {        this.number = number;    }    @Override    public Object clone() {        Student stu = null;        try{            stu = (Student)super.clone();   //浅复制        }catch(CloneNotSupportedException e) {            e.printStackTrace();        }        stu.addr = (Address)addr.clone();   //深度复制        return stu;    }}public class Test {    public static void main(String args[]) {        Address addr = new Address();        addr.setAdd("杭州市");        Student stu1 = new Student();        stu1.setNumber(123);        stu1.setAddr(addr);        Student stu2 = (Student)stu1.clone();        System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());        System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());        addr.setAdd("西湖区");        System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());        System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());    }}

结果:

学生1:123,地址:杭州市  学生2:123,地址:杭州市  学生1:123,地址:西湖区  学生2:123,地址:杭州市

来源地址:https://blog.csdn.net/wangshiqi666/article/details/130228941

--结束END--

本文标题: Java基础:对象的克隆(复制)

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

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

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

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

下载Word文档
猜你喜欢
  • Java基础:对象的克隆(复制)
    假如想复制一个简单变量。很简单: int apples = 5;int pears = apples; 不仅int类型,其它七种原始数据类型(boolean,char,byte,short,float,double.long)同样适用于该类...
    99+
    2023-09-26
    数据结构
  • java 对象的克隆(浅克隆和深克隆)
    java 对象的克隆一、对象的浅克隆(1)需要克隆类需要重写Object类的clone方法,并且实现Cloneable接口(标识接口,无需实现任何方法) (2)当需要克隆的对象中维护着另外一个引用对象,浅克隆不会克隆另外一个引用对下,而是直...
    99+
    2023-05-31
    java 对象 克隆
  • JAVA对象创建与对象克隆
    目录一、对象的4种创建方式二、通过new创建对象三、反射四、克隆对象浅拷贝深拷贝五、反序列化六、补充一、对象的4种创建方式 new 创建反射克隆反序列化 二、通过new创建对象 一般...
    99+
    2024-04-02
  • Java编程实现对象克隆(复制)代码详解
    克隆,想必大家都有耳闻,世界上第一只克隆羊多莉就是利用细胞核移植技术将哺乳动物的成年体细胞培育出新个体,甚为神奇。其实在Java中也存在克隆的概念,即实现对象的复制。本文将尝试介绍一些关于Java中的克隆和一些深入的问题,希望可以帮助大家更...
    99+
    2023-05-30
    java 对象 克隆
  • JAVA对象创建与对象克隆的方法
    这篇文章主要介绍了JAVA对象创建与对象克隆的方法的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JAVA对象创建与对象克隆的方法文章都会有所收获,下面我们一起来看看吧。一、对象的4种创建方式new 创建反射克隆...
    99+
    2023-06-29
  • java怎么实现对象克隆
    在Java中,可以通过两种方式来实现对象克隆:浅拷贝和深拷贝。1. 浅拷贝:使用Object类的clone()方法进行对象的浅拷贝。...
    99+
    2023-08-18
    java
  • Java对象克隆怎么实现
    本篇内容主要讲解“Java对象克隆怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java对象克隆怎么实现”吧! Overiew在实际编程中,我们经常会遇到这样一个情景:有一个对象A,存在...
    99+
    2023-06-17
  • java克隆对象的方法有哪些
    在Java中,克隆对象的方法有以下几种:1. 实现Cloneable接口并重写clone()方法:该方法是Object类中的方法,需...
    99+
    2023-09-25
    java
  • Java克隆对象的特性是什么
    本篇内容介绍了“Java克隆对象的特性是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在java面向对象的编程当中,要复制引用类型的对象...
    99+
    2023-06-17
  • java克隆对象实现的方法有哪些
    在Java中,有以下几种方法可以实现对象的克隆:1. 实现Cloneable接口并重写clone()方法:这是最常见和最简单的方式。...
    99+
    2023-08-24
    java
  • vue对象的深度克隆方式
    目录vue对象的深度克隆方法1方法2方法3vue克隆对象时遇到的问题vue对象的深度克隆 方法1 通过js序列化,将js转换成字符串,然后再将字符串转换成js对象 var olbOb...
    99+
    2024-04-02
  • 如何解析Java语言的对象克隆特性
    这篇文章将为大家详细讲解有关如何解析Java语言的对象克隆特性,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。在Java中传值及引伸深度克隆的思考中,我们讲过引申到克隆技术Java中的所有对象...
    99+
    2023-06-17
  • Java引用对象深度克隆的方法是什么
    在Java中,要实现对象的深度克隆,你可以使用以下方法之一:1. 实现`Cloneable`接口并重写`clone()`方法:```...
    99+
    2023-09-27
    Java
  • Java基础——类和对象
    目录 一、类和对象的基本概念 二、类与对象的定义与使用 1.创建类的语法: 2. 创建具体的对象:  3.范例(创建一个Person 类的对象)  三、static关键字   (一)static修饰属性(类属性、类变量) (二)static...
    99+
    2023-10-05
    java
  • VB.NET对象克隆的主要思想是什么
    VB.NET对象克隆的主要思想是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。VB.NET编程语言中对对象的操作是比较重要的一个操作技巧,对于一个具有面向对...
    99+
    2023-06-17
  • JavaScript如何实现多级对象的深度克隆
    这篇文章给大家分享的是有关JavaScript如何实现多级对象的深度克隆的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。多级对象的深度克隆要深度克隆多级对象,可以遍历每个属性,并检查当前属性是否包含对象。如果是,则...
    99+
    2023-06-27
  • JavaScript中合并和克隆对象的示例分析
    小编给大家分享一下JavaScript中合并和克隆对象的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!当我们想要复制原始值和引用值(对象)时,它们的行为会大不相同。原始值我们假设一个变量 name 具有一个与之关联...
    99+
    2023-06-15
  • python基础之面对对象基础类和对象的概念
    简称oop 复习 面向对象编程,简称oop [object oriented programming] 是一种python的编程思想 面...
    99+
    2024-04-02
  • 〔005〕Java 基础之面向对象
    ✨ 目录 ▷ 面向对象▷ 注意事项▷ this关键字▷ 构造器▷ 重载构造方法▷ 实体类▷ 案例:英雄搜索 ▷ 面向对象 对象: 是一种特殊的数据结构对象: 使用类 new 出来的,有了类就可以创建对象,例...
    99+
    2023-12-22
    java 开发语言 经验分享 极限编程 重载 面向对象
  • Java面向对象基础详解
    目录一、前言什么是对象?什么是类?类和对象的关系?类的定义 ?怎么创建对象?格式:创建对象的作用?Phone类下: PhoneDemo下:二、封装封装的好处?Student...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作