String_StringBuilder_StringBuffer 区别
1.String:
String类是final修饰的,属于不可变(immutable)类,每次对原对象操作都会产生新的String对象。
源码中String类的定义:private final char value[];
可以看出用于存放字符的数组被声明为 final 的,因此只能赋值一次,不可再更改。
2.StringBuffer 和 StringBuilder区别:
两者都继承了一个抽象的字符串父类:AbstractStringBuilder。
StringBuffer 和 StringBuilder 它们都属于可变的字符串,都是在原对象上进行操作。
区别1:线程安全
StringBuffer:线程安全,StringBuilder:线程不安全。
因为 StringBuffer 的所有公开方法都是 synchronized 修饰的,而 StringBuilder 没有 修饰。
StringBuffer 的 append()方法源码:
@Override public synchronized StringBuffer append(String str) { toStringCache = null; super.append(str); return this; }
区别2:缓冲区
StringBuffer 的 toString()方法源码:
private transient char[] toStringCache; @Override public synchronized String toString() { if (toStringCache == null) { toStringCache = Arrays.copyOfRange(value, 0, count); } return new String(toStringCache, true); }
StringBuilder 的 toString()方法源码:
@Override public String toString() { // Create a copy, don't share the array return new String(value, 0, count); }
StringBuffer 每次获取 toString 都会直接使用缓存区的 toStringCache 值来构造一个字符串。
而 StringBuilder 则每次都需要复制一次字符数组,再构造一个字符串。
所以,缓存冲这也是对 StringBuffer 的一个优化吧,不过 StringBuffer 的这个toString() 方法仍然是同步的。
区别3:性能
既然 StringBuffer 是线程安全的,它的所有公开方法都是同步的,StringBuilder 是没有对方法加锁同步的,
因此性能上:StringBuilder > StringBuffer > String。
3.使用场景
1. 基本原则:如果要操作少量的数据,用String ;单线程操作大量数据,用StringBuilder ;多线程操作大量数据,用StringBuffer。
2. 不要使用String类的 "+" 来进行频繁的拼接,因为那样的性能极差的,应该使用StringBuffer或StringBuilder类,这在Java的优化上是一条比较重要的原则。
例如:
String result = ""; for (String s : hugeArray) { result = result + s; } // 使用StringBuilder StringBuilder sb = new StringBuilder(); for (String s : hugeArray) { sb.append(s); } String result = sb.toString();
显然采用第二种方法效率更搞,因为第一种方法每次循环都会创建一个String result用于保存结果。
3. 为了获得更好的性能,在构造 StringBuffer 或 StringBuilder 时应尽可能指定它们的容量。
当然,如果你操作的字符串长度(length)不超过 16 个字符就不用了,当不指定容量(capacity)时默认构造一个容量为 16 的对象,不指定容量会显著降低性能。
4. StringBuilder 一般使用在方法内部来完成类似 + 功能,因为是线程不安全的,所以用完以后可以丢弃。
而StringBuffer 主要用在全局变量中。
5. 相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
而在现实的模块化编程中,负责某一模块的程序员不一定能清晰地判断该模块是否会放入多线程的环境中运行,
因此:除非确定系统的瓶颈是在 StringBuffer 上,并且确定你的模块不会运行在多线程模式下,才可以采用 StringBuilder;否则还是用 StringBuffer。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?