时间: 2021年2月25日星期四 多云
前言
面试是类似演讲演说的过程,网上的资料都是文字的,没法让面试者直观的体验到面试过程,本人已经将相关内容制作成音频节目,有兴趣的朋友可以去喜马拉雅搜索《2020年Java面试208题》收听音频版节目。
《2020年Java面试208题》整理了208个Java程序员的面试题,主要是针对三年以内开发经验的JAVA程序员提出的问题。
题目
本期要说的是《2020年Java面试208题》的第6题,面试官提了这样一个问题: java 中操作字符串都有哪些类?它们之间有什么区别?
知识点分析
这个题目说起来简单,但其中涉及到不可变对象的概念,我得先把不可变对象这个事儿说说,否则描述String的性能低的问题我怕有人不服(理解困难)。
String对象是不可变对象,这个概念怎么理解呢?也就是String类在设计的时候Sun公司的大牛没有给他设计值修改的功能,程序员使用String的时候只能在new构造方法的时候获得一个初始值,之后就不允许修改其中的值了。
有的人肯定就不服了,不对啊,我明明看到String可以用+符号做联结啊,也可以执行replace方法,也有substring做截断,咋就成了不可修改了?
我们如果认真读一读String的源代码就会发现,其实每次操作都不是对原String对象的值进行修改,而是重新new了一个String对象。
假设,我们有一个String对象a,我们希望在a后面加一个字符串”abc”,代码写出来是a=a+”abc”,或者a=a.concat(“abc”),我们以为是在a对象的值后面加了几个字符,其实过程是读出a原来的字符数组,然后读出字符常量”abc”,然后使用StringBuffer类进行字符串拼接,拼接完毕后得到新的字符串,再把变量a指向到这个新的字符串。
因此可以看出,每次我们以为对字符串对象进行值修改,其实都是新生成了一个字符串对象。
希望上面的描述让你对Java的不可变对象有所了解。
演示面试
现在就由我来演示一下面试:
你好,面试官。
1 首先 Java中操作字符串的类有3个,String,StringBuilder,StringBuffer ,都是用来联结、截断、操作字符串的。
在核心上字符串就是字符的数组,String、StingBuilder、StringBuffer的源代码中都有一个私有变量保存着字符数组。
不同之处只在于性能和线程安全性问题。
String的性能最差,StringBuilder的性能最好,StringBuffer相对StringBuilder慢一些。
然后我具体解释一下他们的性能问题。
2 String对象是不可变对象,所以性能最差。
不可变对象的意思是对象的值是不可变的,你定义了一个String对象值为abc,就无法再改变值内容了,改变值内容其实是创建了一个新对象。
这样的特性就造成,String对象做 + 联结操作的过程是新创建一个对象的过程,如果只做少量的值变更性能影响并不大,如果在循环中执行大量的值变更操作,那么对性能的影响是明显的。
3 StringBuilder性能最好,线程不安全
在StringBuilder内部管理一个字符数组来存储字符串内容,如果对字符串变更后的长度不大于字符数组长度,就直接在当前字符数组上进行操作;如果新的字符串长度超过数组长度的话,就新创建字符数组替换现有的字符数组,新的字符数组长度为当前字符数组的两倍,并将字符串内容写入到字符数组中。
通过这样一种模式可以看出,大多数情况下,都是在已经开辟的字符数组空间中进行内存操作,不会创建新的对象,性能得到极大提高。
并且StringBuilder在设计的时候并不考虑多线程并发问题,因此代码更加精简,性能是最好的。
4 StringBuffer机制与StringBuilder完全一样,性能略差,因为增加了线程安全
因此StringBuffer相对StringBuilder性能差了一点点,但相应的对于多线程场景下,StringBuffer的稳定性和容错性要好的多。
=========================================================
好了,以上就是我的演示面试,不知道是否让你满意。
下期再见
本人技术有限,只是希望给程序员面试提供一点帮助,必有不足之处,希望业内人士积极批评指正,在留言区留言就是对我最大的鼓励。希望批评中肯一些,不要存在人身攻击,更不要波及到家人,善意中肯的批评我都能够虚心接受。 我们下期再见。