Java对象克隆-浅拷贝与深拷贝

news2025/1/12 18:13:56

目录

1、对象的克隆

1.1 对象的浅拷贝

1.2 对象深拷贝


1、对象的克隆

1.1 对象的浅拷贝

在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也就是说,A与B是两个独立的对象,但B的初始值是由A对象确定的。

要满足这种需求虽然有很多途径,但实现clone()方法是其中最简单,也是最高效的手段。

public class Person implements Cloneable {

   private String name;

   private int age;

   public Person() {

   }

   public Person(String name, int age) {

      this.name = name;

      this.age = age;

   }

   public String getName() {

      return name;

   }

   public void setName(String name) {

      this.name = name;

   }

   public int getAge() {

      return age;

   }

   public void setAge(int age) {

      this.age = age;

   }

   protected Object clone() {

      Object obj = null;

      try {

         obj = super.clone();

      } catch (CloneNotSupportedException e) {

         e.printStackTrace();

      }

      return obj;

   }

   public String toString() {

      return "Person [name=" + name + ", age=" + age + "]";

   }

}

注意: 该Person 类实现了Cloneable 重写了clone() 方法.

public static void main(String[] args) {

      Person p1 = new Person("jack", 28);

      System.out.println(p1);

      Person p2 = (Person) p1.clone();

      System.out.println(p2);

      // 不是同一个Person 对象.

      System.out.println(p1 == p2);

      // 修改p1 对象属性值,不影响 p2 对象的属性值.

      p1.setAge(30);

      System.out.println(p1);

      System.out.println(p2);

   }

Java的所有类都默认继承java.lang.Object类,在java.lang.Object类中有一个方法clone()。JDK API的说明文档解释这个方法将返回Object对象的一个拷贝。要说明的有两点:一是拷贝对象返回的是一个新对象,而不是一个引用。二是拷贝对象与用new操作符返回的新对象的区别就是这个拷贝已经包含了一些原来对象的信息,而不是对象的初始信息。

1.2 对象深拷贝

注意问题:

请看代码:

package cn.test.gz.myclone;

public class Person implements Cloneable {

   private String name;

   private int age;

   private Address add;

   public Person() {

   }

   public Person(String name, int age, Address add) {

      this.name = name;

      this.age = age;

      this.add = add;

   }

   public String getName() {

      return name;

   }

   public void setName(String name) {

      this.name = name;

   }

   public int getAge() {

      return age;

   }

   public void setAge(int age) {

      this.age = age;

   }

   public Address getAdd() {

      return add;

   }

   public void setAdd(Address add) {

      this.add = add;

   }

   protected Object clone() {

      Object obj = null;

      try {

         obj = super.clone();

      } catch (CloneNotSupportedException e) {

         e.printStackTrace();

      }

      return obj;

   }

   @Override

   public String toString() {

      return "Person [name=" + name + ", age=" + age + ", add:" + add + "]";

   }

}

package cn.test.gz.myclone;

public class Address {

   private String country;

   private String city;

   public Address() {

   }

   public Address(String country, String city) {

      this.country = country;

      this.city = city;

   }

   public String getCountry() {

      return country;

   }

   public void setCountry(String country) {

      this.country = country;

   }

   public String getCity() {

      return city;

   }

   public void setCity(String city) {

      this.city = city;

   }

   public String toString() {

      return "country=" + country + ", city=" + city;

   }

}

注意:

Address add = new Address("中国", "广州");

      Person p1 = new Person("jack", 28, add);

      add.setCountry("美国");

      System.out.println(p1);

      Person p2 = (Person) p1.clone();

      System.out.println(p2);

      // 克隆的是两个不同的对象

      System.out.println(p1 == p2);

      // 但是对象内部的成员是同一个对象.

      System.out.println(p1.getAdd() == p2.getAdd());

解决办法:

package cn.test.gz.myclone;

public class Address implements Cloneable {

   private String country;

   private String city;

   public Address() {

   }

   public Address(String country, String city) {

      this.country = country;

      this.city = city;

   }

   public String getCountry() {

      return country;

   }

   public void setCountry(String country) {

      this.country = country;

   }

   public String getCity() {

      return city;

   }

   public void setCity(String city) {

      this.city = city;

   }

   public String toString() {

      return "country=" + country + ", city=" + city;

   }

   @Override

   public Object clone() {

      Object obj = null;

      try {

         obj = super.clone();

      } catch (CloneNotSupportedException e) {

         // TODO Auto-generated catch block

         e.printStackTrace();

      }

      return obj;

   }

}

Person 类

protected Object clone() {

      Person p = null;

      try {

         p = (Person) super.clone();

      } catch (CloneNotSupportedException e) {

         e.printStackTrace();

      }

      p.add = (Address) add.clone();

      return p;

   }

当然也可以通过序列化机制来实现对象的克隆.

public static void main(String[] args) throws IOException, ClassNotFoundException {

      Address add = new Address("中国", "广州");

      Person p1 = new Person("jack", 28, add);

      ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(

            "c:\\person.txt"));

      oos.writeObject(p1);

      ObjectInputStream ois = new ObjectInputStream(new FileInputStream("c:\\person.txt"));

      Person p2=(Person)ois.readObject();

      System.out.println(p1==p2);

      System.out.println(p1.getAdd()==p2.getAdd());

   }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1609424.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PHP定时任务框架taskPHP3.0学习记录4宝塔面板bash定时任务(轮询指定json文件字段后确定是否执行、环境部署、执行日志、文件权限)

一 需求说明 宝塔面板中,读取指定 /www/wwwroot/lockdata/cron/webapp.json文件;配置定时任务脚本task.sh;当读取webapp.json中,如果cron_task1,则执行任务php start.php start命令行;完成命令后,执行cron…

AJAX——图书管理案例

1.渲染列表 自己的图书数据:给自己起个外号,并告诉服务器,默认会有三本书,基于这三本书做数据的增删改查。 // 目标1:渲染图书列表 // 1.1 获取数据 // 1.2 渲染数据const creator 哈哈 // 封装-获取并渲染图书列表函…

使用共振峰提取元音因素/从声音生成口型动画

视频效果 我前段时间研究了下从声音提取共振峰的方法。今天测试了下实际效果。 我使用一段33秒的女声视频,提取原因后使用静态视位图序列生成了一个视频,效果如下: b站视频:https://www.bilibili.com/video/BV1JD421H7m9/?vd_s…

前端开发与html学习笔记

一、前端开发概述 前端开发:也叫做web前端开发,它指的是基于web的互联网产品的页面(也可叫界面)开发及功能开发互联网产品:指网站为满足用户需求而创建的用于运营的功能及服务,百度搜索、淘宝、QQ、微博、网易邮箱等都是互联网产…

Postman调用OpenApi接口

首先你需要科学上网。。。。。 请求方式:post 请求地址:https://api.openai.com/v1/chat/completions 请求头: Authorization : Bearer key Content-Type : application/json Body : { "messages": [{ "role": &quo…

基于SSM+Jsp+Mysql的房屋租赁系统

开发语言:Java框架:ssm技术:JSPJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包…

【C++打怪之路】-- C++开篇

🌈 个人主页:白子寰 🔥 分类专栏:C打怪之路,python从入门到精通,魔法指针,进阶C,C语言,C语言题集,C语言实现游戏👈 希望得到您的订阅和支持~ &…

得物sign参数逆向分析与Python算法还原

文章目录 1. 写在前面2. 接口分析3. 断点分析4. Python算法还原 【🏠作者主页】:吴秋霖 【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚…

C++修炼之路之继承<二>

目录 一:子类的六大默认成员函数 二:继承与友元 三:继承与静态成员 四:复杂的继承关系菱形继承菱形虚拟继承 1.单继承 2.多继承 3.菱形继承;一种特殊的多继承 4.菱形虚拟继承 5.虚拟继承解决数据冗余和二…

Spectre-v1 简介以及对应解决措施

文章目录 前言一、Variant 1: Exploiting Conditional Branches.二、 BACKGROUND2.1 Out-of-order Execution2.2 Speculative Execution2.3 Branch Prediction2.4 The Memory Hierarchy2.5 Microarchitectural Side-Channel Attacks2.6 Return-Oriented Programming 三、 ATTAC…

阿里云OSS 存储对象的注册与使用

目录 一、什么是阿里云OSS 二、 点击免费试用 2.1 选择第一个,点击免费试用 ​编辑 2.2 登录管理控制台 2.3 进入Bucket 2.4、在阿里云网站上的个人中心配置Accesskey,查询accessKeyId和accessKeySecret。 2.5、进入AccssKey管理页面应该会出现下图提示&…

前端从零到一搭建脚手架并发布到npm

这里写自定义目录标题 一、为什么需要脚手架?二、前置-第三方工具的使用1. 创建demo并运行-4步新建文件夹 zyfcli,并初始化npm init -y配置入口文件 2.commander-命令行指令3. chalk-命令行美化工具4. inquirer-命令行交互工具5. figlet-艺术字6. ora-lo…

QT跨平台读写Excel

QT跨平台读写Excel 背景Excel工具CMakeLists.txt工程目录 背景 开发框架QT,makefile构建工具CMake,编译器MinGW Excel工具 考虑跨平台则不能使用针对微软COM组件的QAxObject来读写Excel,因此使用开源QtXlsx。 这里是将QXlsx当做源码嵌入使…

门禁管理系统服务器如何内网映射让外网访问?

禁管理系统整体解决方案,可实现请假出入联动、门状态监控、电子地图、非法闯入报警、远程开门、红外防夹、智能统计等功能,应用非常广泛。 如果门禁管理系统部署在没有公网IP的本地服务器上,如何设置,能让外网互联网上也能登录访问内部的管理…

亚马逊云科技AWS CloudUp for Her送亚马逊认证考试50%优惠券活动

最近总有小伙伴问小李哥,有没有送AWS考试50%优惠券的活动?这次送云从业者(cloud practitioner)、助理级架构师(SAA)考试50%优惠券活动就来了! 本次活动叫AWS CloudUp for Her,完成免费在线培训课程即可获得AWS证书考试50%折扣券&a…

ZooKeeper设置监听器

ZooKeeper设置监听器,通过getData()/getChildern()/xists()方法。 步骤: 1.创建监听器:创建一个实现Watcher接口的类,实现process()方法。这个方法会在ZooKeeper向客户端发送一个Watcher事件通知的时候被调用。 2.注册监听器&…

Servlet第四篇【request对象常用方法、应用】

什么是HttpServletRequest HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。 简单来说,要得…

蓝桥杯竞赛类型:Web应用开发 全程详解

既然大家准备报名蓝桥杯,那么对蓝桥杯就应该有一定的了解了。没有了解也没关系,简单来说,蓝桥杯就是一个计算机竞赛,竞赛类型大多是使用各种语言写算法,当然还有本文的主体——Web应用开发。对蓝桥杯有了基本了解之后&…

C#使用PaddleOCR进行图片文字识别✨

PaddlePaddle介绍✨ PaddlePaddle(飞桨)是百度开发的深度学习平台,旨在为开发者提供全面、灵活的工具集,用于构建、训练和部署各种深度学习模型。它具有开放源代码、高度灵活性、可扩展性和分布式训练等特点。PaddlePaddle支持端…

IntelliJ IDEA2020下使用Maven构建Scala 项目

1.创建maven文件 2.进入pom.xml导入依赖 <!--添加spark的依赖--><dependency><groupId>org.apache.spark</groupId><artifactId>spark-core_2.12</artifactId><version>3.2.1</version></dependency><!--添加scala依…