Java面试-基础篇之4
String、StringBuffer、StringBuilder的区别与联系
首先,String、StringBuffer和StringBuilder都是操作字符串的数据的类。
不同的是,从源码角度来看,String是继承自Object祖宗类,实现Serializable(可序列化接口)、Comparable
而StringBuffer和StringBuilder继承自AbistractStringBuilder抽象类,以及实现了一个与String不同的接口,Appenable(可追加功能的接口),此接口可以使StringBuffer和StringBuilder拥有追加字符串的能力,该能力与String不同。
可追加字符串,在表面上看来,这3个类都可以实现字符串的追加。String类使用“+”号拼接字符串,看上去好像是将两个以上的字符串拼成了一个,StringBuffer和StringBuilder使用append方法在当前末尾将字符串追加到原字符串上。String类的加号拼接与其他两个类的追加是有很大的区别的。
这就要说到String类的源码了,String类内部没有提供修改字符串的方法,且String类被final修饰不可以被继承,所以String声明的字符串都是不可变的。这里有个问题,用加号看上去这不还是一个变量吗?例如String s1 = "我是第一个字符串",s1 = s1 + "我是第二个";但是,第二个用加号拼起来的字符串和第一个是完全不同的两个对象,在实际的内存中,程序是为拼接后的字符串重新开辟了空间,s1的引用地址指向的是拼接后的内存对象,而声明的第一个堆内存对象已经是个垃圾了。
所以在实际的开发种,如果遇到频繁变动String数据的,千万不要使用String类型加号拼接的方式,那样会让堆内存不断产生垃圾,影响性能。
我们理想中的字符串拼接应该是在同一个位置对字符串进行一个修改,拼接完成的字符串应该代替原有的对象位置的数据,表现为一种更新状态。而StringBuffer和StringBuilder正是使用该方法更新了字符串。因为其内部委会了一个可变的char[]数组,且非final修饰,该数组存放在堆内存种,只有当堆内存不足时,才会开辟更大的空间,再将原数组拷贝,引用地址再指向新的空间。Java9更新后,String。StringBuffer和Stringbuilder中的数组类型改为了占据空间更小的byte[]数组,byte占一个字节(8位),char占两个字节(16位),byte比char更省空间。
3个类在多线程环境下的安全方面也不相同。String对象是不可变的,可视为常量,某种意义上是线程安全的。
StringBuffer是线程安全的,因为StringBuffer中的方法都是用synchronzied修饰。
StringBuilder是线程不安全的。如果在多线程环境下使用字符串,可选择StringBuffer,如果在单线程环境下,还是使用 StringBuilder,因为它的效率比StringBuffer要高。为啥效率高,因为StringBuilder没有加锁,没有锁消耗, StringBuffer不管多线程还是单线程都是加锁使用,所以单线程下没有必要用它。
下节预告:synchronized关键字
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)