你还在使用 StringBuffer ?

介绍

  Java中常用字符串处理类包括 String、StringBuffer 和 StringBuilder ,当对字符串进行修改的时候,使用 StringBuffer 和 StringBuilder 一般比使用 String 效率更高。因为 StringBuffer 的内部实现方式和 String 不同,StringBuffer 在进行字符串处理时,不生成新的对象,在速度和内存使用上都要优于 String

String

  String 是被 final 关键字修饰的,它是不可变的,就算调用 String 的 concat 方法,那也只是把字符串拼接起来并重新创建一个新对象,把拼接后的 String 的值赋给新创建的对象。在这里插入图片描述

StringBuffer

  StringBuffer 是可变的,调用StringBuffer 的 append 等方法,来改变 StringBuffer ,相比较于 String 创建新对象,StringBuffer 的 append 等方法直接在原对象上操作,不新建对象,是更高效的,所以如果需要对字符串进行修改推荐使用 StringBuffer。

StringBuilder

  StringBuilder 在 Java 5 中被提出,它拥有与 StringBuffer 几乎相同的方法与用法,但是无论哪方面都完胜 StringBuilder。

StringBuffer vs StringBuilder

  StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder,在 AbstractStringBuilder 类中也是使用字符数组保存字符串。StringBuffer 很多方法都是 synchronized 修饰的,所以我们常说 StringBuffer 是线程安全的,官方的注释也写着 StringBuffer 是一个线程安全的可变的字符序列,StringBuffer 可以安全的在多线程场景下使用,但事实并非如此官方对StringBuilder注释
  事实上,StringBuffer 不是线程安全的,而且效率低下,任何出现 StringBuffer 的地方都可以用 StringBuilder 去替换。道理很简单, append 等方法在多线程环境下,它能保证程序运行结果的正确性和一致性吗?试想一下,使用 append 拼接 SQL,在多线程环境运行,你根本无法预测最终结果,不光无法预测,JVM 自己都不确定最终结果。
  StringBuffer 的线程安全,仅仅是保证 JVM 不抛出异常顺利的往下执行而已,它不保证逻辑正确和调用顺序正确。大多数时候,我们需要的不仅仅是线程安全,而是锁。事实上,你根本找不到一个用 StringBuffer 的理由,《Effective java》的作者 Joshua Bloch 在书中说:
原文:StringBuffer instances are almost always used by a single thread, yet they perform internal synchronization. It is for this reason that StringBuffer was supplanted by StringBuilder, which is just an unsynchronized StringBuffer.
译文:StringBuffer 实例几乎总是由单个线程使用,但它们执行内部同步。正是由于这个原因,StringBuffer 被 StringBuilder 取代,后者只是一个不同步的StringBuffer。

为什么会有 StringBuffer 的存在呢?如果真的没有价值,为什么 JDK 会提供这个类?

  因为最早是没有 StringBuilder 类的,sun 公司的人错误地决定让 StringBuffer 是线程安全的,然后大约 10 年之后,人们终于意识到这是一个多么愚蠢的决定,意识到在这 10 年之中这个愚蠢的决定为 Java 运行速度慢这样的流言贡献了多大的力量,于是,在 JDK1.5 的时候,终于决定提供一个非线程安全的 StringBuffer 实现,并命名为 StringBuilder 。

总结

线程安全性能(一般情况)使用环境
String少量数据
StringBuffer单线程环境
StringBuilder单线程环境

StringBuffer 基本没有适用场景,你应该在所有的情况下坚定地选择使用 StringBuilder。

posted @ 2021-10-12 00:54  Acx7  阅读(58)  评论(0编辑  收藏  举报