诡异的字符串问题。。。

简介: 说问题前,我先跟各位读者聊一下字符串这个话题,谈起字符串也就离不开数据结构

那问题来了,什么是数据结构呢?我之前也想过怎么优雅的来回答这个问题,每次总感觉自己给出的答案不够准确。于是我便请教了「木马之王」—— Chigo,他的回答很精炼,说出了我想要表达的意思,「数据结构就是结构化的数据模型,方便计算机存储和构造数据,比如字符串、数组、List、Set、Map、Class 、树、图等」,以后别人面试你的时候,你可以用得上^_^。


对于 Java 而言,它不仅提供八种内置基本数据类型,还提供了很多丰富的拓展数据类型,之所以要提供这么多的数据类型,就是便于我们这些懒惰的程序员使用「如果你想成为一名优秀的工程师,还是值得花时间去研究这些数据结构类型的」。


好了,言归正传,今天就来聊一下 String、StringBuffer 和 StringBuilder 这三个字符串处理类。


这三个类,我相信大大小小的面试基本上都会问。今天咱们不聊面试,只来排雷。


image.png


就发展历史而言,StringBuilder 都晚于它的两个老大哥,它是在 JDK 5 中才出现的,网上很多文章都说它与 StringBuffer 没得什么区别只是去掉了 sychronized 关键字「线程安全」部分。


其实对于 JDK 7 及之前的版本可以这么说,但是对于 JDK 8 以后,StringBuffer 是加了 toStringCache 缓存字段的,而且这个字段是用 transient 关键字修饰的,肯定有些读者不知道这个关键字是干嘛的,如果你用过一些序列化的工具,一定对这个关键字不会陌生,被这个关键字修饰过的属性,是不会被序列化的,换句话来说,就是这个字段只会存在于内存之中。


总的来说,JDK 8 之后 StringBuffer 还是有一点儿改变的,后面我们详细来谈谈它具体的改变。对于它们而言,都继承自 AbstractStringBuilder,其实说白了,StringBuffer 和 StringBuilder 的具体操作都是由 AbstractStringBuilder 来实现的,重点看一下它内部是如何扩容的。


对于 String 而言,我觉得是很基础而有特别重要的类,说得难听点,你只要还想吃 Java 这口饭,这个类你必须要掌握。它可聊的话题就太多了,比如它的不可变性?JDK 6 为什么不推荐使用它的 intern() 方法?它到底是值类型还是引用类型?JDK 8 之后,常量池有那些变化?各个版本的 JDK 在编译期间对它进行那些优化?JDK 9 以后存储数据的 char 数组发生了那些改变? 云云。。。


案例 1


我之前在网上看到一个案例,特别具有代表性,在这里给各位读者分享一下。


线上服务器负载过高而导致系统报警。


一般来说,负载过高,多半是某个程序在不停的消耗 CPU 而引起的。引起该问题的代码如下,见下图。


image.png


如果你根据堆栈信息进行分析,就会发现 CPU 在不停的执行拷贝动作,是什么原因导致的呢?


如果你熟悉 StringBuffer 的话,那么很快可以定位到,是 buf.toString() 导致的。有的读者可能会问你怎么知道呢?看一下它的源码不就知道了嘛。。。


image.png

image.png

image.png

注意到没,System.arraycopy() 这个函数就是问题症结,这是一个内存拷贝函数,直接操作系统内存。


问题找到了,那么也就可以抓药了,对于这类的问题,说白了还是开发者自己重复制造轮子所致,其实这也是我一直在团队强调的,有好的轮子就不要自己去制造,编码规范一定要统一起来。


案例 2


可能有读者朋友知道,我最近建了一个技术交流群,群里主要讨论技术,也会不时的有老司机开车「记得系好安全带」。这不,一个同学发现关于 IDEA 的调试问题,目前这个问题,我们还没有找到具体的症结,感兴趣的朋友一起研究一下。


开发环境:JDK 1.8


工具:Eclipse MyEclipse IDEA


具体描述:在如下的代码中,跟下图一样打上断点,注意一定要跟进 StringBuffer 源码里面,在 Eclipse 和 MyEclipse 能按照预期结果返回,但是 IDEA 中却不能正常返回。


image.png


在红线处,打上断点。


image.png


点击红圈,跟进到 StringBuffer 源码「如果你细心的话,一定注意到 append 方法跟 1.7 有所不同」,出现如下图所示。


image.png


image.png 

image.png


你会发现 toStringCache 的值未被置 null,因此,导致还是去返回缓存里面的值,最终结果为「111」,而非「111222」,见下图。


image.png


但是,在 Eclipse 中,toStringCache 的值被置 null 了,见下图。


image.png


这个问题,我觉得还是挺有意思的,我初步怀疑可能是 IDEA 的问题,但是如果 IDEA 不设置断点,返回结果就跟预期的一样「111222」。


如果你找到了原因,欢迎留言告诉我~~~


今天的分享就到这里了,写一篇文章挺费时间的,希望各位读者转发一下,忆蓉君在此谢谢各位了。


参考

http://www.blogjava.net/xylz/archive/2012/03/15/371966.html

https://stackoverflow.com/questions/51814522/run-and-debug-have-different-results-in-method-named-append-in-stringbuffer

相关文章
|
6月前
|
存储 数据库 Python
怎么解决字符乱码的问题
怎么解决字符乱码的问题
62 0
|
数据采集 Java 机器人
根据正则表达式截取字串符,这个办法打败99%程序员
作为一名程序员,常常会在以下情况下使用函数功能根据正则表达式截取字符串:
[疑难杂症系列]程序出错的原因居然因为一个神奇的汉字:㝢
一个导出为EXCEL文件功能之前运行正常,突然出错了。
53 0
|
6月前
|
算法
面试题 01.01:判定字符是否唯一
面试题 01.01:判定字符是否唯一
38 0
|
Java
Java正则表达式(一看就懂)(下)
4.正则表达式-参考附录 参照帮助文档,在 Pattern 类中有正则表达式的的规则定义,正则表达式中明确区分大小写字母。我们 来学习语法规则。 4.1规则
101 0
|
Java 数据安全/隐私保护 Python
Java正则表达式(一看就懂)(上)
看了热榜正则表达式都上榜了目前正则表达式榜一是Python的 经过这几天呕心沥血不眠不休 终于今天Java的正则表达式它来了 还有练习题 耗时9981个小时 都是干货 赶紧收藏起来!!!!
92 0
|
Python
7-ELEVEn中的“n”为啥要小写?答案匪夷所思...
7-ELEVEn中的“n”为啥要小写?答案匪夷所思...
99 0
|
JavaScript 流计算
收藏!!最全的字符串函数方法,看完再也不会忘记了~
收藏!!最全的字符串函数方法,看完再也不会忘记了~
【编程】89%的人不知道的字符拼接成字符串的注意点
【编程】89%的人不知道的字符拼接成字符串的注意点
84 0
|
Java Python
Java正则表达式(一看就懂)
Java正则表达式(一看就懂)
226 0
Java正则表达式(一看就懂)