当前位置: 首页 > news >正文

读《Effective Java》笔记 - 条目13

条目13:谨慎重写clone方法

浅拷贝和深拷贝

浅拷贝(Shallow Copy)

浅拷贝 只复制对象本身,而不复制对象引用的成员。 对于引用类型的字段,浅拷贝会将原对象的引用复制到新对象中,而不会创建新对象实例。因此,原对象和拷贝对象中的引用字段将指向相同的内存地址。

浅拷贝的特点:

  • 复制对象的时候,如果是基本数据类型会被完全复制。
  • 对于引用数据类型,比如数组,集合,自定义对象等,都是复制引用而不是实际的数据对象。
  • 浅拷贝通常是通过Object.clone()方法实现的。

示例:

class Person {String name;int[] age;public Person(String name, int[] age) {this.name = name;this.age = age;}// 浅拷贝public Person shallowCopy() {try {Person cloned = (Person) super.clone();  // 复制对象return cloned;} catch (CloneNotSupportedException e) {e.printStackTrace();return null;}}
}public class Main {public static void main(String[] args) {int[] ages = {25, 30, 35};Person person1 = new Person("John", ages);// 浅拷贝Person person2 = person1.shallowCopy();// 修改 person2 的 age 数组person2.age[0] = 40;System.out.println("person1's age: " + person1.age[0]);  // 40System.out.println("person2's age: " + person2.age[0]);  // 40}
}

person1person2age 数组是共享的,因为浅拷贝仅复制了 age 数组的引用。当 person2 修改了 age[0] 的值时,person1age[0] 也发生了变化。

深拷贝

深拷贝是指不仅复制对象本身,还递归地复制对象所引用的所有对象

深拷贝的特点:

  • 深拷贝会复制对象及其所有引用对象。
  • 每个引用类型字段都会被复制为一个全新的实例,因此原对象和拷贝对象中的引用字段指向不同的内存地址。
  • 深拷贝通常需要手动实现,尤其是在对象中包含其他引用类型。

示例:

class Person implements Cloneable {String name;int[] age;public Person(String name, int[] age) {this.name = name;this.age = age;}// 深拷贝@Overridepublic Person clone() {try {Person cloned = (Person) super.clone();  // 复制对象cloned.age = this.age.clone();  // 深拷贝数组return cloned;} catch (CloneNotSupportedException e) {e.printStackTrace();return null;}}
}public class Main {public static void main(String[] args) {int[] ages = {25, 30, 35};Person person1 = new Person("John", ages);// 深拷贝Person person2 = person1.clone();// 修改 person2 的 age 数组person2.age[0] = 40;System.out.println("person1's age: " + person1.age[0]);  // 25System.out.println("person2's age: " + person2.age[0]);  // 40}
}

person1person2age 数组是完全独立的,因为我们在 clone() 方法中对 age 数组进行了深拷贝。修改 person2age[0] 不会影响 person1age[0]

Coneable接口

clone() 方法是 Object 类的一部分,因此所有的 Java 类都可以通过实现 Cloneable 接口来使得自己支持克隆。然而,问题在于 Cloneable 接口本身并没有提供任何方法,它只是一个标志,表示该类允许被克隆。要想正确的实现克隆,需要我们需要在类中覆盖 clone() 方法。如果直接使用弗雷的clone()方法,可能会在某些情况下得到不符合预期的结果。

建议

  1. 考虑使用构造函数代替clone()方法
  2. 如果决定重写clone()方法,需要调用super.clone()来确保父类对象的字段也会被复制,如果没有,可能会导致父类无法正确的被克隆。
  3. 如果要处理字段是引用类型(对象)的情况时,需要对这些字段创建新的实例,从而确保是深拷贝。
  4. clone() 方法必须声明为 public,因为它是从 Object 类继承来的,默认是 protected,因此在覆盖时需要改变它的访问修饰符。
  5. clone() 方法必须抛出 CloneNotSupportedException 异常,这是因为 Cloneable 接口并不是强制要求实现的,如果一个类没有实现 Cloneable 接口而调用 clone(),将会抛出这个异常。
  6. 要么完全重写,要么不重写。如果重写的话,就需要全面考虑所有的字段。特别是当对象包含复杂的嵌套结构时,确保每一个引用字段都能正确的被复制。
  7. 复制最好通过构造器或者工厂来提供。

相关文章:

读《Effective Java》笔记 - 条目13

条目13:谨慎重写clone方法 浅拷贝和深拷贝 浅拷贝(Shallow Copy) 浅拷贝 只复制对象本身,而不复制对象引用的成员。 对于引用类型的字段,浅拷贝会将原对象的引用复制到新对象中,而不会创建新对象实例。因…...

SQL 之连接查询

SQL 连接查询:深入理解 JOIN 操作 在数据库管理中,连接查询(JOIN)是一种基本而强大的操作,它允许我们从两个或多个表中检索数据。SQL 中的 JOIN 操作使得数据整合变得简单,这对于数据分析和报告至关重要。…...

vscode切换anaconda虚拟环境解释器不成功

问题: 切换解释器之后运行代码还是使用的原来的解释器 可以看到,我已经切换了“nlp”解释器,我的nltk包只在“nlp”环境下安装了,但是运行代码依然是"torch"解释器,所以找不到“nltk”包。 在网上找了各种…...

一个实用的 Maven localRepository 工具

目录 1 现状2 当前解决3 更好的解决3.1 下载 Maven localRepository 工具包3.2 上传本地 localRepository 包3.3 清理 localRepository 中指定后缀的文件 1 现状 在使用 Maven 时,我们可能会经常与本地仓库和私服仓库打交道。 例如对于本地仓库,因为某…...

目标检测,图像分割,超分辨率重建

目标检测和图像分割 目标检测和图像分割是计算机视觉中的两个不同任务,它们的输出形式也有所不同。下面我将分别介绍这两个任务的输出。图像分割又可以分为:语义分割、实例分割、全景分割。 语义分割(Semantic Segmentation)&…...

微信小程序 城市点击后跳转 并首页显示被点击城市

在微信小程序中,渲染出城市列表后,如何点击城市,就跳转回到首页,并在首页显示所点击的城市呢? 目录 一、定义点击城市的事件 二、首页的处理 首页:点击成都市会跳转到城市列表 城市列表:点击…...

Linux - nfs服务器

五、nfs服务器 1、基础 NFS服务器可以让PC将网络中的NFS服务器共享的目录挂载到本地端的文件系统中,而在本地端的系统 中看来,那个远程主机的目录就好像是自己的一个磁盘分区一样。 由于NFS支持的功能比较多,而不同的功能都会使用不同的程…...

uniapp图片上传预览uni.chooseImage、uni.previewImage

文章目录 1.上传图片2.预览图片 1.上传图片 uni.chooseImage(OBJECT) 从本地相册选择图片或使用相机拍照。 App端如需要更丰富的相机拍照API(如直接调用前置摄像头),参考plus.camera 微信小程序从基础库 2.21.0 开始, wx.choos…...

C++ 字符串中数字识别

【问题描述】 输入一个字符串,含有数字和非数字字符,如“sumabc234;while(abc700)tab{ass346;bssabc267;}”,将其中连续的数字作为一个整数,依次存放到一个数组nums中。例如,234放在nums[0],700放在nums[1…...

学术中常见理论归纳总结-不定期更新

1.信息传播类 1.1 扩散创新理论 创新扩散理论是传播效果研究的经典理论之一,是由美国学者埃弗雷特罗杰斯(E.M.Rogers)于20世纪60年代提出的一个关于通过媒介劝服人们接受新观念、新事物、新产品的理论,侧重大众传播对社会和文化的影响。 1927-1941年进行的“艾奥瓦杂交玉…...

ModelSim怎么修改字体及大小

点击TOOLS 选择PERFERENCES选择下一级菜单的TEXTFONT/CHOOSE/选择字体和大小最后不要忘记点apply再退出...

图片预处理技术介绍4——降噪

图片预处理 大家好,我是阿赵。   这一篇将两种基础的降噪算法。   之前介绍过均值模糊和高斯模糊。如果从降噪的角度来说,模糊算法也算是降噪的一类,所以之前介绍的两种模糊可以称呼为均值降噪和高斯降噪。不过模糊算法对原来的图像特征的…...

Scrapy管道设置和数据保存

1.1 介绍部分: 文字提到常用的Web框架有Django和Flask,接下来将学习一个全球范围内流行的爬虫框架Scrapy。 1.2 内容部分: Scrapy的概念、作用和工作流程 Scrapy的入门使用 Scrapy构造并发送请求 Scrapy模拟登陆 Scrapy管道的使用 Scrapy中…...

D84【python 接口自动化学习】- pytest基础用法

day84 pytest常用断言类型 学习日期&#xff1a;20241130 学习目标&#xff1a;pytest基础用法 -- pytest常用断言类型 学习笔记&#xff1a; 常用断言类型 代码实践 def test_assert():assert 11assert 1!2assert 1<2assert 2>1assert 1>1assert 1<1assert a…...

如何正确书写sh文件/sh任务?bash任务

正确书写xx.sh文件的方式为&#xff1a; source /usr/local/miniconda3/bin/activate condaEnv export CUDA_VISIBLE_DEVICES0 cd /hy-tmp/test export PYTHONPATH"xxx:$PYTHONPATH" python AAA.py python BBB.py python CCC.py 直接运行&#xff1a; bash xx.sh 即可…...

多线程篇-5--线程分类(线程类型,springboot中常见线程类型,异步任务线程)

常见的线程类型包括用户线程&#xff08;User Threads&#xff09;、守护线程&#xff08;Daemon Threads&#xff09;、主线程&#xff08;Main Thread&#xff09;、工作线程&#xff08;Worker Threads&#xff09;和线程池中的线程。 一、用户线程&#xff08;User Thread…...

docker快速部署gitlab

文章目录 场景部署步骤默认账号密码效果 场景 新增了一台机器, 在初始化本地开发环境&#xff0c;docker快速部署gitlab 部署步骤 编写dockerfile version: 3.7services:gitlab:image: gitlab/gitlab-ce:latestcontainer_name: gitlabrestart: alwayshostname: gitlabenviron…...

C# 数据类型详解:掌握数据类型及操作为高效编码奠定基础

本文将带你深入了解C#中各种数据类型的特点、用途和最佳实践&#xff0c;让你不仅能熟练运用基本类型&#xff0c;还能掌握如何在实际项目中做出最合适的选择。 目录 C#基本语法 C#数据类型 C#类型转换 C#变量常量 C#基本语法 在学习C#之前我们要先知道C#的基础构建是由哪些…...

burp2

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…...

[ACTF2020 新生赛]BackupFile--详细解析

信息搜集 让我们寻找源文件&#xff0c;目录扫描&#xff1a; 找到了/index.php.bak文件&#xff0c;也就是index.php的备份文件。 后缀名是.bak的文件是备份文件&#xff0c;是文件格式的扩展名。 我们访问这个路径&#xff0c;就会直接下载该备份文件。 我们把.bak后缀删掉…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

深入浅出Diffusion模型:从原理到实践的全方位教程

I. 引言&#xff1a;生成式AI的黎明 – Diffusion模型是什么&#xff1f; 近年来&#xff0c;生成式人工智能&#xff08;Generative AI&#xff09;领域取得了爆炸性的进展&#xff0c;模型能够根据简单的文本提示创作出逼真的图像、连贯的文本&#xff0c;乃至更多令人惊叹的…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!

目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

实战设计模式之模板方法模式

概述 模板方法模式定义了一个操作中的算法骨架&#xff0c;并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下&#xff0c;重新定义算法中的某些步骤。简单来说&#xff0c;就是在一个方法中定义了要执行的步骤顺序或算法框架&#xff0c;但允许子类…...