前言

只有光头才能变强。

文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y

记录一次在写代码时愚蠢的操作,本文涉及到的知识点:String不可变性

一、交代背景

我这边有一个系统,提供一个RPC接口去发送短信。外部调用我的接口需要传入手机号等等参数,我这边负责解析这些参数、做一些业务的处理,然后调用短信渠道商的接口发送短信。

每当调用完短信渠道商的接口时,我会对这次发送的记录入库(存入MySQL中),同样地短信渠道商会返回发送或失败的回执给我,我也会入库(存入MySQL中)。

那天,有人来找到我,说某个手机号收不到短信,用户并没有屏蔽短信(欠费、关机)等等一些操作,就是收不到短信。

于是我就去排查啦,首先我先去DB里边找有没有对应的发送记录,发现这条记录是存在的,而且在DB上看不出来有什么异常。

后来就去捞日志,看看调用短信运营商返回的Result对象的信息是什么,然后就去问了一下短信运营商可能出现这种问题的原因是什么。那边回复的是:“如果是部分的手机号出现这种状况,是不是你们的手机号没有trim啊?

于是,我又去捞日志,发现手机号后面真的带有一个空格(扎心了,之前一直看不到)。要处理这个问题就变得异常简单了,我只要在入口里边对手机号进行trim就好了。

二、编写代码

我这边是支持同一条短信向多个手机号发送,于是手机号我这边用的是HashSet来进行接收。对手机号进行trim我写下了如下的代码:

// 说明:Task对象 有个 key属性,这个key属性的类型是HashSetif (task.getKey() != null && task.getKey().size() > 0) {    for (String s : task.getKey()) {        s.trim();    }}

if (task.getKey() != null && task.getKey().size() > 0) {    for (String s : task.getKey()) {        s.trim();    }}

代码很简单,我做的就两步:

上面的代码有问题吗?必须有问题啊,没问题我还写啥。

下面写个小Demo,我们会发现:在代码的11行上调用trim()方法后,在12行再输出,还是会有空格的情况。

代码示例

2.1 为什么会有这种错觉?

其实,我们在初学Java的时候,肯定会学到String类。在学习的时候也是明确String是不可变的,但总是有个感觉我们把String对象给改了,为什么?

不可变的String

我觉得第一点是这样的:我们操作的往往是可变的对象,对象的某些属性改了,我们就认为已经改了。比如下面的代码:

HashSet<Student> students = getStudent();for (Student s1 : students) {    s1.setName("Java3y");}for (Student s1 : students) {    s1.setName("Java3y");}

执行完,我们就认为在HashSet里边的Student的名字全改成Java3y了,而实际上也是如此。

我觉得第二点是这样的:我们平时操作String对象,都是直接把操作后的结果传过去,这看起来就像修改原对象了一样。比如下面类似的代码:

// 去重String phone = "   137888888888    ";sendPhone(phone.trim());// 转成大写后输出System.out.println(phone.toUpperCase());// ... 等等String phone = "   137888888888    ";sendPhone(phone.trim());

// 转成大写后输出System.out.println(phone.toUpperCase());

// ... 等等

返回一个新的String对象

2.2 怎么改

现在问题已经知道了,String对象是不可变的,对String对象进行操作,“看似”把原来的String对象改了,实际上是生成了一个新的String对象。

回到我那个问题,也很好解决,把trim好的手机号设置到HashSet就行了

// 说明:Task对象 有个 key属性,这个key属性的类型是HashSetHashSet<String> hs = new HashSet();if (task.getKey() != null && task.getKey().size() > 0) {    for (String s : task.getKey()) {        hs.add(s.trim());    }}task.setKey(hs);

HashSet<String> hs = new HashSet();if (task.getKey() != null && task.getKey().size() > 0) {    for (String s : task.getKey()) {        hs.add(s.trim());    }}task.setKey(hs);

最后

这个B写了一篇文章来解释自己是怎么“合理“写Bug的,真tm不要脸。

推荐阅读:

  • 大佬准备了一年时间拿到今日头条offer

  • 进程之间究竟有哪些通信方式?---- 告别死记硬背

  • 什么是列式存储?

  • 硬核干货长文!Hbase来了解一下不?

  • 程序员的快乐就是这么朴素无华且枯燥

  • 互联网/电商/广告常见的术语

  • 拿到一台新的Windows电脑,我会做什么?

  • 在公司做的项目和自己在学校做的有什么区别


200多篇原创技术文章海量视频资源精美脑图面试题

长按扫码可关注获取

欢迎关注点个再看

记一次愚蠢的操作--String不可变性相关推荐

  1. 记一次愚蠢的操作--线程安全问题

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:github.com/ZhongFuChen- 记一次在工作中愚蠢的操作,本文关键字:线程安全 (我怎么天天在写Bug啊) 一 ...

  2. Go 学习笔记(60)— Go 第三方库之 go-redis(初始化 redis、操作 string、操作 list、操作 set、操作 hset)

    1. 第三方库 go-redis 因为 Go 标准库中是没提供 redis 的库,所以我们选择用 go-redis 这个第三方库.源码地址为 https://github.com/go-redis/r ...

  3. 分布式内存数据库---Redis操作String、list、set、hash和Zset

    Redis是一个Key-Value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合)和zset(有序集合).这些数据类 ...

  4. 网易视频云技术分享:记一次.gitignore的操作细节

    网易视频云是网易倾力打造的一款基于云计算的分布式多媒体处理集群和专业音视频技术,提供稳定流畅.低时延.高并发的视频直播.录制.存储.转码及点播等音视频的PAAS服务,在线教育.远程医疗.娱乐秀场.在线 ...

  5. 常见操作String的方法(截取子串,分割字符串,字符串的替换)

    常见操作String的方法(截取子串,分割字符串,字符串的替换) 截取子字符串substring() substring()方法有两种重载形式,一种是从指定位置截取到字符串结尾,另一种是截取指定范围的 ...

  6. 常见操作String的方法(字符查找,索引查找)

    常见操作String的方法(字符查找,索引查找) 在给定的字符串中查找字符或字符串是比较常见的操作.字符串查找分为两种形式:一种是在字符串中获取匹配字符(串)的索引值,另一种是在字符串中获取指定索引位 ...

  7. Python中 redis StrictRedis对象操作string类型

    Python中 redis StrictRedis对象操作string类型 准备 在桌面上创建redis目录 使用pycharm打开 redis目录 创建redis_string.py文件 from ...

  8. Redis常用命令之操作String类型

    场景 Centos中Redis的下载编译与安装(超详细): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103967334 Re ...

  9. jedis set集合 java,使用Jedis操作String、List、Set、Map等常见数据 | zifangsky的个人博客...

    Jedis属于Java连接Redis的一种客户端.其操作方式跟原生的redis客户端命令类似.关于redis操作的基本命令可以参考这个文档:http://www.runoob.com/redis/re ...

最新文章

  1. 图文解读:5 个刁钻的 String 面试题!
  2. Openstack贡献者须知 2 — 社区工作运作 代码贡献流程
  3. 171. Excel Sheet Column Number
  4. java解析静态AIS原始数据
  5. Python_str 的内部功能介绍
  6. 牛客题霸 [删除有序链表中重复的元素] C++题解/答案
  7. java进程和线程_Java™ 教程(进程和线程)
  8. 大学python教材思维导图_Python核心知识体系的14张思维导图
  9. linux网关管理,利用Linux打造安全的管理型网关
  10. MySQL报错The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents .....
  11. 直播盒子APP源码AlijuheCMS™开发手册之接口文档 for IOS
  12. Action为何要继承ActionSupport类
  13. x64 盗版PCHunter
  14. 今天通过了QCC评审
  15. 液压机行业研究及十四五规划分析报告
  16. bootmgr is missing
  17. 如何使用脚本语言将typora的内容自动同步到gitee上
  18. TCP短连接与长连接
  19. 怎么修改html模板里的背景,怎么修改网页背景
  20. Java-面向对象 练习题

热门文章

  1. 淘客必看的抖音引流到微信的方案
  2. 应用程序正常初始化(0xc0000135)失败
  3. 基于elementui源码实现自定义穿梭框transfer组件
  4. python做万花筒代码_Python实现PS滤镜的万花筒效果示例
  5. 1050: 阶乘的累加和 C语言
  6. 特斯拉市值破万亿,贡献了过半销量的中国市场居功至伟
  7. Python字母数字下划线生成田字格随机密码
  8. ftp软件,国内好用的ftp软件
  9. 了解RISC-V指令集架构
  10. 可用于标记蛋白质216699-36-4,6-ROX,SE,6-羧基-X-罗丹明琥珀酰亚胺酯