Java高效编程(12):重写toString方法
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界
尽管 Object 类提供了 toString 方法的默认实现,但它返回的字符串通常不是类的使用者想要看到的。默认返回的字符串格式是类名加上“@”符号和哈希码的十六进制表示,例如 PhoneNumber@163b91。然而,toString 方法的合同要求返回一个简洁且信息丰富的字符串表示,以便用户阅读。显然,与“707-867-5309”相比,“PhoneNumber@163b91”并不具备太多的可读性和信息量。因此,建议重写 toString 方法。
虽然重写 toString 不如重写 equals 和 hashCode 那样重要(如【条目10】和【条目11】所述),但提供一个良好的 toString 实现能让你的类更加易用,且有助于调试。当对象被传递给 println、printf、字符串连接操作符或断言语句时,toString 会自动调用。即使你不主动调用 toString,其他人可能会。例如,某个组件在记录错误消息时可能会包含对象的字符串表示。如果你没有重写 toString,这些消息几乎是无用的。
为什么要重写 toString
如果你为 PhoneNumber 提供了一个好的 toString 方法,那么生成有用的诊断消息会变得非常简单:
System.out.println("Failed to connect to " + phoneNumber);
不论你是否重写 toString,程序员通常都会以这种方式生成诊断消息,但只有当你重写了 toString,这些消息才真正有用。toString 的好处不仅体现在类的实例本身,也会反映在包含这些实例的对象上,特别是集合。比如,当你打印一个 Map 时,哪一个更可读:{Jenny=PhoneNumber@163b91} 还是 {Jenny=707-867-5309}?
toString 方法应尽可能返回对象中的所有有趣信息。对于较大的对象或不适合字符串表示的对象,可以返回摘要信息,例如 Manhattan residential phone directory (1487536 listings) 或 Thread[main,5,main]。理想情况下,字符串应该是自解释的。
格式化和文档化
实现 toString 时,一个重要的决定是是否要在文档中指定返回值的格式。对于像电话号码这样的值类,建议指定格式,因为这可以为对象提供一种标准且明确的表示,可以用于输入、输出以及持久化数据(如 CSV 文件)。如果你指定了格式,最好提供匹配的静态工厂方法或构造函数,以便程序员能够在对象和字符串表示之间轻松转换。许多 Java 平台库中的值类(如 BigInteger、BigDecimal 和大多数包装类)都采用了这种方法。
指定 toString 格式的缺点是,一旦你指定了格式,就必须长期坚持使用,特别是当你的类被广泛使用时。如果将来修改了表示格式,可能会导致程序崩溃或数据损坏。因此,如果你不指定格式,就保留了将来改进格式的灵活性。
无论是否指定格式,都应该明确记录你的意图。如果指定格式,要精确说明。例如,下面是与【条目11】中的 PhoneNumber 类相匹配的 toString 方法文档:
/*** 返回该电话号码的字符串表示。* 字符串由十二个字符组成,格式为“XXX-YYY-ZZZZ”,* 其中 XXX 是区号,YYY 是前缀,ZZZZ 是号码。* * 如果这三个部分中的任意一部分不够长,会用前导零填充。* 例如,如果号码值是 123,字符串表示的最后四个字符将是“0123”。*/
@Override
public String toString() {return String.format("%03d-%03d-%04d", areaCode, prefix, lineNum);
}
如果你选择不指定格式,则文档注释可能会类似如下:
/*** 返回该药水的简短描述。表示的具体细节未指定,并且可能会变化,* 但通常的格式可能如下:** "[Potion #9: type=love, smell=turpentine, look=india ink]"*/
@Override
public String toString() {// 自定义实现
}
这种文档确保了使用者在解析字符串表示时不能抱怨格式变化引发的问题。
提供访问器
无论是否指定 toString 格式,都应提供程序化访问对象信息的途径。以 PhoneNumber 类为例,应该提供获取区号、前缀和号码的访问器。如果没有这些访问器,程序员不得不解析字符串来获取这些信息,这不仅降低了性能,还可能导致错误的系统。如果没有访问器,即使你声明字符串格式是可变的,它实际上仍然会成为一个事实上的 API。
特殊情况
不必在静态工具类(【条目4】)或大多数 enum 类型中编写 toString 方法,因为 Java 已经为 enum 提供了一个很好的默认实现。不过,在抽象类中,如果子类共享相同的字符串表示形式,则应该编写 toString 方法。例如,许多集合实现继承了抽象集合类的 toString 实现。
此外,Google 的开源 AutoValue 工具可以自动生成 toString 方法,绝大多数 IDE 也提供了自动生成 toString 的功能。这些自动生成的方法对于了解类的字段内容非常有用,但并不适合表示类的特定含义。例如,电话号码类应该有一个标准的字符串表示,而药水类则可以接受自动生成的 toString 方法。不过,自动生成的 toString 方法仍然比继承自 Object 的默认实现好得多,后者几乎无法提供任何有用信息。
总结
除非超类已经重写了 toString,否则在你编写的每个实例类中都应重写 toString。这会让你的类更易用,并有助于调试。toString 方法应返回对象的简洁、有用的描述,并且格式美观。
相关文章:
Java高效编程(12):重写toString方法
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 尽管 Object 类提供了 toString 方法的默认实现,但它返回的字符串通常不是类的使用者想要看到的。默认返回的字符串格式是类名加上“”符号和哈希码的十六进制表示,例如 PhoneNu…...
谷歌给到的185个使用生成式AI的案例
很多公司从利用AI回答问题,进而使用AI进行预测,向使用生成式AI Agent转变。AI Agent的独特之处在于它们可以采取行动以实现特定目标,比如引导购物者找到合适的鞋子,帮助员工寻找合适的健康福利,或在护理人员交接班期间…...
程序员如何通过专业与软技能提升核心竞争力
一、引言 随着AIGC的兴起,AI辅助编程工具如chatgpt、midjourney、claude等接二连三地涌现,编程领域的变革正逐步深化。面对这一变革,程序员们对于未来工作的前景有着种种不同的担忧和期待。他们担心AI可能取代部分编程工作,同时…...
基于YOLOv8的智能植物监测机器人
摘要:针对传统的植物病害检测方法依赖专家的经验,耗时耗力,并且准确性受限于个人的水平等问题。文中提出无线通信模块采用HTTP协议来传输数据图片,采用SoC核心处理器实现了便携化,采用对射式红外避障传感器实现自动避障功能。以YOLOv8算法为控制核心,并添加注意力机制以提…...
2024年OpenAI DevDay发布实时 API、提示缓存等新功能
就在几天前,一些重要人物如前 CTO Mira Murati 离开了 OpenAI。因此,看到 Sam Altman 在 DevDay 上登台,讨论开发者的新产品,感觉有点奇怪。 随着公司内部的这些变化,你不禁会想:我们还应该信任他吗&#…...
Raspberry Pi3B+之安装bookworm+Rpanion系统
Raspberry Pi3B之安装bookwormRpanion系统 1. 源由2. 系统安装3. 系统安装3.1 烧录系统3.2 设备接线3.3 配置无线3.4 更新系统3.5 安装git3.6 克隆Rpanion3.7 安装Rpanion 4. 系统管理5. 附录问题1:error: externally-managed-environment问题2:bookworm…...
无人机专业除理论外,飞手执照、组装、调试实操技术详解
无人机专业的学习除了丰富的理论知识外,飞手执照的获取、无人机的组装与调试等实操技术也是至关重要的。以下是对这些方面的详细解析: 一、无人机飞手执照 1. 必要性 法规要求:根据《民用无人驾驶航空器系统驾驶员管理暂行规定》等相关法规…...
【网路通信基础与实践番外二】TCP协议的流量控制和拥塞控制以及二者区别和例题
TCP协议是端对端的协议,因此在数据进行传输的过程受发送方,数据通道,接收方三方状态的影响。我们用水龙头来比喻数据发送方,水管来比喻数据通道,水桶来表示数据接收方。 图(a)表示水桶太小,来不及接受注入…...
SpringBoot3+Vue3开发后台管理系统脚手架
后台管理系统脚手架 介绍 在快速迭代的软件开发世界里,时间就是生产力,效率决定成败。对于构建复杂而庞大的后台系统而言,一个高效、可定制的后台脚手架(Backend Scaffold)无疑是开发者的得力助手。 脚手架 后台脚…...
OpenFeign微服务部署
一.开启nacos 和redis 1.查看nacos和redis是否启动 docker ps2.查看是否安装nacos和redis docker ps -a3.启动nacos和redis docker start nacos docker start redis-6379 docker ps 二.使用SpringSession共享例子 这里的两个例子在我的一个博客有创建过程,…...
【C语言】数组(下)
【C语言】数组(下) 6、二维数组的创建6.1二维数组的概念6.2二维数组的创建 7、二维数组的初始化7.1不完全初始化7.2完全初始化7.3按照行初始化7.4初始化时可以省略行,但是不能省略列 8、二维数组的使用8.1 二维数组的下标8.2二维数组的输入和…...
cGANs with Projection Discriminator
基于映射鉴别器的CGAN 模型中,判别器(Discriminator)不是通过将条件信息简单地与特征向量拼接(concatenate)来使用条件信息,而是采用一种基于投影的方式,这种方式更加尊重条件信息在底层概率模…...
mysql学习教程,从入门到精通,SQL HAVING 子句(32)
1、SQL HAVING 子句 当然!HAVING 子句在 SQL 中用于对分组后的结果进行过滤。它通常与 GROUP BY 子句一起使用,以便对聚合函数(如 SUM(), COUNT(), AVG(), MAX(), MIN() 等)的结果进行条件筛选。 以下是一个示例,假设…...
JavaScript while循环语句
While语句包括一个循环条件和一段代码块,只要条件为真,就不断循环执行代码块。 while(条件){语句;} var i0;while(i<100){console.log(i);i1;} 注意:所有的for循环都可以改写为while循环...
49天精通Java(Day 2):Java的基本语法
上期内容回顾 在上一期的内容中,我们介绍了Java的基本概念、历史背景,并完成了JDK 1.8的安装与环境配置。你还编写并运行了第一个简单的Java程序“Hello, World!”。今天,我们将深入探讨Java的基本语法,包括变量、数据类型、运算…...
uni-app之旅-day01-home页
首页 3.0 创建 home 分支 🍕🍕🍕运行如下的命令,基于 master 分支在本地创建 home 子分支,用来开发和 home 首页相关的功能git branch(查看分支)git checkout -b home(创建home分支) 3.1 配置网络请求 ἲ…...
Vue3轻松实现导出Excel文件功能
文章目录 1.前言2.安装插件3.案例3.1 定义表格数据,设置 id 选择器3.2 据所选 dom 对象生成 sheetbook3.3 写入文件3.4 生成 xlsx文件4.完整代码1.前言 前端常用的导出 Excel的 js 库是 xlsx,但是 xlsx不能设置样式。要想设置样式,必要要结合 xlsx-style 插件一起使用,但是…...
在Kali Linux中使用VNC和iptables配置xrdp以实现远程连接
在Kali Linux中,使用VNC和iptables配置xrdp以实现远程连接涉及几个步骤。不过,值得注意的是,VNC和xrdp是两种不同的远程桌面协议,它们通常不会在同一配置中同时使用(除非有特殊的网络架构需求)。然而&#…...
小徐影院:Spring Boot技术下的影院革新
第四章 系统设计 4.1 系统的功能结构图 通过系统需求分析,本小徐影城管理系统的功能结构设计如图4-1所示: 图4-1 系统功能图 4.2 系统数据库设计 4.2.1 数据库E-R图 在该系统的信息中,由于数据库的支持,我们可以对数据库进行收集…...
命名空间
在 C 中,变量、函数和类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突,使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace 关键字的…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
