前言

只有光头才能变强。
文本已收录至我的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();    }}

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

  • 判断是否为null,不为null值则遍历手机号集合
  • 对每个手机号进行trim
    上面的代码有问题吗?必须有问题啊,没问题我还写啥。

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

记一次愚蠢的操作--String不可变性
代码示例

2.1 为什么会有这种错觉?

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

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

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

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

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

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

记一次愚蠢的操作--String不可变性
返回一个新的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);

最后

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

推荐阅读:

  • 大佬准备了一年时间拿到今日头条offer
  • 进程之间究竟有哪些通信方式?---- 告别死记硬背
  • 什么是列式存储?
  • 硬核干货长文!Hbase来了解一下不?
  • 程序员的快乐就是这么朴素无华且枯燥
  • 互联网/电商/广告常见的术语
  • 拿到一台新的Windows电脑,我会做什么?
  • 在公司做的项目和自己在学校做的有什么区别
    记一次愚蠢的操作--String不可变性

200多篇原创技术文章
海量视频资源
精美脑图
面试题
长按扫码可关注获取

更多相关文章

  1. Github标星19K+Star,10分钟自建对象存储服务!
  2. golang 发送post请求 其body中json对象使用变量作为value
  3. Java 程序员应该知道的 10 个面向对象理论
  4. 一个GCRoot不可达的对象,会立刻被垃圾回收吗?
  5. Object对象你真理解了吗?
  6. HotSpot VM 中对象的内存分析
  7. 从对象生命周期的经验统计到垃圾回收算法
  8. 什么样的 Java 对象会被当垃圾回收?

随机推荐

  1. Android开发中Virtual Device仿真界面对
  2. Android(安卓)Api 常用类库包介绍
  3. 如何在Android中启动JAVA程序
  4. Android模拟器无法上网的解决方法
  5. 获取 + 查看 Android 源码的 方法
  6. android矢量图vector的简单介绍
  7. Android实现动态改变屏幕方向(Landscape &
  8. Android Studio系列教程三--快捷键
  9. Android之音量调节
  10. Android应用程序——四大组件之Activity