对于所有对象都通用的方法⭐良好习惯总结

对于所有对象都通用的方法⭐良好习惯总结

Object是每个类的父类,它提供一些非final方法:equals、hashCode、clone、toString、finalize...

这些方法在设计上是可以被子类重写的,但是重写前需要遵守相关的规定,否则在使用时就可能踩坑

为了避免业务开发踩坑,本文基于Effective Java中第三章节汇总出对于所有对象都通用方法的好习惯(文末附案例地址)

finalize方法上篇文章已经描述就不再讨论

1.重写equals的通用规定

equals是Object中提供比较对象逻辑相等的方法

在Object中equals方法比较对象引用地址是否相同,相同则返回true

public boolean equals(Object obj) {return (this == obj);
}

如果想让对象逻辑相等,则可以重写equals方法

但在重写equals方法前需要遵守一些规定:

  1. 自反性:x.equals(x)需要返回true
  2. 对称性:x.equals(y)返回true,那么y.equals(x)也要返回true
  3. 传递性:x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也要true
  4. 一致性:x.equals(y)返回true,只要x\y都没被修改多次执行都返回true
  5. 非null的x: x.equals(null) 要返回 false
  6. 重写equals必须重写hashCode

如果要实现equals,通用情况可以使用以下总结:

  1. 先判断对象的引用地址是否相等,相等则返回true
  2. 判断两个对象是否为相同类型,不同类型则返回false
  3. 转换成相同类型后根据规定逻辑相等的关键字段进行比较,相等返回true

比如String中的equals就是这样重写的:

public boolean equals(Object anObject) {//1.判断对象的引用地址是否相等if (this == anObject) {return true;}//2.判断两个对象是否为相同类型if (anObject instanceof String) {//3.转换成相同类型后根据规定逻辑相等的关键字段进行比较String anotherString = (String)anObject;int n = value.length;if (n == anotherString.value.length) {char v1[] = value;char v2[] = anotherString.value;int i = 0;while (n-- != 0) {if (v1[i] != v2[i])return false;i++;}return true;}}return false;
}

也可以使用工具去进行生成,但要记得重写equals时还需要重写hashCode

重写hashCode也要根据逻辑相等的关键字段进行,能够根据关键字段充分打乱哈希码

如果不遵循约定,那么在使用哈希表的数据结构时可能出现严重的问题

并且使用哈希表时,Key最好是不可变对象如String,或者保证哈希码不变

2.始终要重写toString

在Object的toString中返回:全限定类名 + @ + 哈希码的十六进制

public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

使用起来十分不方便,不好调试,查看对象信息

因此最好对其进行重写,返回容易阅读、有用的对象信息

3.谨慎重写clone

clone方法提供克隆一个新的对象,重写时使用super.clone()进行克隆

clone方法坑多,重写时需要谨慎

  1. 如果重写clone需要实现Cloneable接口(该接口是一个空接口)否则就会抛出不支持克隆的运行时异常(这是Cloneable设计上的缺陷)

    protected native Object clone() throws CloneNotSupportedException;
  2. 在clone的重写时,super.clone() 使用的是浅拷贝,如果字段存在对象,想要深拷贝对象,则对象也要重写clone方法

    class CloneObject implements Cloneable {private int num;private CloneA cloneA = new CloneA(99);@Overrideprotected CloneObject clone() throws CloneNotSupportedException {CloneObject res = (CloneObject) super.clone();//深拷贝:CloneA也要重写clone实现Cloneableres.cloneA = cloneA.clone();return res;}   
    }
  3. 如果字段是final的,则无法使用深拷贝

    因为深拷贝时还需要去调用clone进行赋值:res.cloneA = cloneA.clone();

  4. 一个实体类携带克隆的方法,耦合性较高,违反单一职责

4.考虑实现Comparable接口

有的对象如果你需要对它进行排序,那么可以实现Comparable接口来进行排序,然后使用一些排序工具如:Arrays.sort

它是一个泛型接口,可以指定需要排序的类型,实现compareTo 负数为小于、正数为大于、零为等于

与其相似功能的另一个接口Comparator是外部比较器,常用于外部排序

  1. Comparator 外部比较器优先Comparable 内部比较器

有时候在一些容器中会需要排序,如果没提供外部比较器也没有实现内部比较器,会导致转换失败抛出异常

如红黑树实现的TreeMap中:

Comparator<? super K> cpr = comparator;
//优先外部排序器
if (cpr != null) {//小于去左子树寻找、大于去右子树寻找、相等替换do {parent = t;cmp = cpr.compare(key, t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;elsereturn t.setValue(value);} while (t != null);
}
else {if (key == null)throw new NullPointerException();@SuppressWarnings("unchecked")//如果未实现内部排序器 则抛出异常Comparable<? super K> k = (Comparable<? super K>) key;do {parent = t;cmp = k.compareTo(t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;elsereturn t.setValue(value);} while (t != null);
}
  1. 使用某些需要排序的容器(TreeMap 红黑树)时,如果不实现比较器在转换时会发生异常
  1. 实现排序时,根据多个关键字段从重要程度依次排序,基本类型可以使用包装类的compare方法

比如需要按照学生年龄排序,那么可以先比较age,age相等再比较day

public int compareTo(Student o) {// int res = this.age - o.age;// 使用包装类的compareint res = Integer.compare(this.age, o.age);if (0 == res) {return Integer.compare(this.day, o.day);}return res;
}
  1. 外部比较器还提供lambda表达式构造Comparator
TreeSet<Student> students = new TreeSet<>(//先比较age再比较dayComparator.comparingInt(Student::getAge).thenComparingInt(Student::getDay)
);
总结

equals表示逻辑相等,当需要判断对象逻辑相等时重写equals方法

重写equals通用方案一般为先判断对象引用是否相等,再判断对象是否为同类型,为同类型再根据关键字段进行比较

重写equals需要根据根据逻辑相等的字段重写hashCode,否则在使用哈希表实现的数据结构时会出现严重问题

使用哈希表时Key最好为不可变对象,或让对象的hashCode不会随着字段值改变,否则会出现严重问题

始终要重写toString,输出关键字段信息,方便阅读、调试

谨慎重写clone,clone用于对象的克隆,在设计上并不太好还存在一些缺点:

  1. 重写clone需要实现Cloneable空接口,否则会抛出 CloneNotSupportedException 异常
  2. 调用 super.clone 实现的是浅拷贝,如果要实现深拷贝,字段中的类也需要重写clone方法
  3. 如果字段是final的则无法实现深拷贝
  4. 实体类携带克隆方法,耦合性较高,违法单一职责

对于需要排序的对象,考虑实现Comparable或Comparator接口:

  1. Comparator 外部比较器一般优先 Comparable 内部比较器
  2. 使用某些需要排序的容器时(红黑树 TreeMap),如果不实现比较器在转换时会发生异常
  3. 实现排序时,根据多个关键字段重要程度进行排序,基本类型可以使用包装类的compare方法
  4. 外部排序器提供lambda表达式构造Comparator外部比较器
最后(不要白嫖,一键三连求求拉~)

本篇文章被收入专栏 Effective Java,感兴趣的同学可以持续关注喔

本篇文章笔记以及案例被收入 Gitee-CaiCaiJava、 Github-CaiCaiJava 感兴趣的同学可以stat下持续关注喔~

有什么问题可以在评论区交流,如果觉得菜菜写的不错,可以点赞、关注、收藏支持一下~

关注菜菜,分享更多干货,公众号:菜菜的后端私房菜

本文由博客一文多发平台 OpenWrite 发布!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单片机之蓝牙通信

目录 蓝牙介绍 HC05蓝牙模块 HC05参数 HC05引脚 各个引脚功能 HC05模块的作用 工作模式 配置模式 引脚接线 用AT指令进行配置 常用的AT指令 正常模式 测试步骤 烧录的程序 前言&#xff1a; keil文件 蓝牙介绍 蓝牙&#xff1a;Bluetooth&#xff0c;其是低成…

ARL资产侦察灯塔系统

1、资产侦察灯塔系统搭建 1.1、系统要求 目前暂不支持 Windows&#xff0c;Linux 和 MAC 建议采用 Docker 运行&#xff0c;系统配置最低 2 核 4G。 由于自动资产发现过程中会有大量的的发包&#xff0c;建议采用云服务器可以带来更好的体验 实验环境&#xff1a; 系统&…

玩机进阶教程------手机定制机 定制系统 解除系统安装软件限制的一些步骤解析

定制机 在于各工作室与商家合作定制rom中有一些定制机。限制用户私自安装第三方软件。或者限制解锁 。无法如正常机登陆账号等等。定制机一般用于固定行业或者一些部门。专机专用。例如很多巴枪扫描机型等等。或者一些小牌机型。对于没有官方包的机型首先要导出各个分区来制作…

【Linux】进程间通信 -- 管道

目录 一. 管道1. 匿名管道1.1. 匿名管道的创建命令行创建pipe() 函数创建 1.2 匿名管道的读写规则1.3 匿名管道的特点 2. 命名管道2.1 命名管道的创建命令行创建mkfifo() 函数创建 2.2 命名管道的读写规则和特点 进程间通信 (Inter-Process Communication, 简称 IPC) 是多进程协…

Mongodb入门--头歌实验MongoDB 复制集 分片

一、MongoDB之副本集配置 1.1MongoDB主从复制 主从复制是MongoDB最早使用的复制方式&#xff0c; 该复制方式易于配置&#xff0c;并且可以支持任意数量的从节点服务器&#xff0c;与使用单节点模式相比有如下优点&#xff1a; 在从服务器上存储数据副本&#xff0c;提高了数…

【软件工程】UML用例图介绍和实例说明

文章目录 1、什么是用例图2、用例图的作用3、怎么画用例图4、三要素说明5、实例说明 1、什么是用例图 用例图&#xff08;Use Case Diagram&#xff09;是统一建模语言&#xff08;UML&#xff09;的一种图&#xff0c;它主要用于描述系统的功能和用户&#xff08;参与者&…

【C++学习】C++智能指针:提高代码安全与性能的利器

文章标题 智能指针的提出智能指针概念及使用RAII 智能指针的原理C库多种智能指针详解版本一&#xff1a;std::auto_ptr&#xff08;C98&#xff09;1. std::auto_ptr 使用2. std::auto_ptr 原理3. std::auto_ptr 模拟实现 版本二&#xff1a;unique_ptr (C11)1. unique_ptr 的使…

数码相框-显示JPG图片

LCD控制器会将LCD上的屏幕数据映射在相应的显存位置上。 通过libjpeg把jpg图片解压出来RGB原始数据。 libjpeg是使用c语言实现的读写jpeg文件的库。 使用libjpeg的应用程序是以"scanline"为单位进行图像处理的。 libjpeg解压图片的步骤&#xff1a; libjpeg的使…

2023年MathorCup数学建模D题航空安全风险分析和飞行技术评估问题解题全过程文档加程序

2023年第十三届MathorCup高校数学建模挑战赛 D题 航空安全风险分析和飞行技术评估问题 原题再现 飞行安全是民航运输业赖以生存和发展的基础。随着我国民航业的快速发展&#xff0c;针对飞行安全问题的研究显得越来越重要。2022 年 3 月 21 日&#xff0c;“3.21”空难的发生…

STM32之HAL开发——FatFs文件系统移植

FatFs文件系统移植 FatFs 程序结构图 移植 FatFs 之前我们先通过 FatFs 的程序结构图了解 FatFs 在程序中的关系网络 用户应用程序需要由用户编写&#xff0c;想实现什么功能就编写什么的程序&#xff0c;一般我们只用到 f_mount()、f_open()、 f_write()、f_read() 就可以…

【vue】watchEffect 自动侦听器

watchEffect&#xff1a;自动监听值的变化 获取旧值时&#xff0c;不是很方便&#xff0c;建议用watch <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevic…

Android Studio 使用Flutter开发第一个Web页面(进行中)

附上Flutter官方文档 1、新建Flutter项目&#xff08;需要勾选web选项&#xff09; 新建项目构成为&#xff1a; 2、配置 Flutter 使用 path 策略 官方文档 在main.dart中&#xff0c;需要导入flutter_web_plugins/url_strategy.dart包&#xff0c;并在main(){}函数中usePath…

影响小程序SSL证书收费标准的因素有哪些?

在当今互联网时代&#xff0c;移动应用发展日新月异&#xff0c;小程序逐渐成为广大企业和个人开发者的心仪之选。然而&#xff0c;伴随小程序的广泛应用&#xff0c;安全问题和用户信任显得尤为关键。为了确保小程序的信息传输安全&#xff0c;SSL证书成为了一项基础配置。那么…

MySQL 表管理

目录 建库 语法&#xff1a; 库名命名规则&#xff1a; 相关命令&#xff1a; 建表 语法&#xff1a; 相关命令&#xff1a; 修改表 语法&#xff1a; 常用操作命令 复制表 数据类型 MySQL的10种常用数据类型&#xff1a; 数据的导入和导出 导入&#xff1a; 格…

Acrobat Pro DC 2023 for mac直装激活版 pdf编辑处理工具

Acrobat Pro DC 2023 for Mac是一款功能强大的PDF编辑器&#xff0c;为用户提供了全面且高效的PDF处理体验。 软件下载&#xff1a;Acrobat Pro DC 2023 for mac直装激活版下载 首先&#xff0c;它支持用户从现有文档创建PDF&#xff0c;或者将其他文件格式如图片、网页等轻松转…

SpringBoot之集成Redis

SpringBoot之集成Redis 一、Redis集成简介二、集成步骤2.1 添加依赖2.2 添加配置2.3 项目中使用 三、工具类封装四、序列化 &#xff08;正常都需要自定义序列化&#xff09;五、分布式锁&#xff08;一&#xff09;RedisTemplate 去实现场景一&#xff1a;单体应用场景二&…

自动化测试(selenium篇)

这次我们来介绍selenium 我们主要来讲解这几个要点 1.什么是自动化测试 2.什么是selenium 3.为什么来讲selenium 4.selenium的环境搭建 5.selenium的 API 1.什么是自动化测试 自动化测试指软件测试的自动化&#xff0c;在预设状态下运行应用程序或者系统&#xff0c;预设条…

海外媒体发稿:探究7个旅游业媒体套餐背后的秘密-华媒舍

旅游业媒体套餐对于旅游行业来说扮演着重要的角色&#xff0c;帮助企业在竞争激烈的市场中宣传推广&#xff0c;吸引更多的游客。在这篇文章中&#xff0c;我们将深入探究7个旅游业媒体套餐背后的秘密&#xff0c;为您揭示其真正的价值和影响。 1. 平台选择的关键 在选择旅游业…

【40分钟速成智能风控11】数据测试与应用

目录 ​编辑 数据测试与应用 联合建模机制 数据质量评估 覆盖率 稳定性 模型效果 投资回报率 线上应用 数据安全合规 数据测试与应用 智能风控模型的搭建离不开机构内外部的数据源&#xff0c;如何从海量数据源中挑选出最合适的部分进行特征工程和风控建模&#xff…

高创新 | [24年新算法]NRBO-XGBoost回归+交叉验证基于牛顿拉夫逊优化算法-XGBoost多变量回归预测

高创新 | [24年新算法]NRBO-XGBoost回归交叉验证基于牛顿拉夫逊优化算法-XGBoost多变量回归预测 目录 高创新 | [24年新算法]NRBO-XGBoost回归交叉验证基于牛顿拉夫逊优化算法-XGBoost多变量回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现 [24年新算…