当前位置: 首页 > news >正文

java基础之String、StringBuilder、StringBuffer的异同

目录

概述

String为何不可变,StringBuilder和StringBuffer为何可变

StringBuffer为何线程安全的,而StringBuilder为何非线程安全

三者性能分析

使用场景


概述

String、StringBuilder和StringBuffer都是用来处理字符串的类,底层都是通过char[]数组实现的。(jdk1.8及之前)

String是不可变的(线程安全的),StringBuilder和StringBuffer是可变的。StringBuffer是线程安全的,而StringBuilder是非线程安全的。具体如下:

String对象一旦创建,其值是不能修改的,如果要修改,会重新开辟内存空间来存储修改之后的对象;而StringBuffer和StringBuilder对象的值是可以被修改的;

StringBuffer几乎所有的方法都使用synchronized实现了同步,线程比较安全,在多线程系统中可以保证数据同步,但是效率比较低;而StringBuilder 没有实现同步,线程不安全,在多线程系统中不能使用 StringBuilder,但是效率比较高。

如果我们在实际开发过程中需要对字符串进行频繁的修改,不要使用String,否则会造成内存空间的浪费;当需要考虑线程安全的场景下使用 StringBuffer,如果不需要考虑线程安全,追求效率的场景下可以使用 StringBuilder。

下面我们从三个维度:可变性、线程安全性、性能来分析区别。

String为何不可变,StringBuilder和StringBuffer为何可变

String部分源码


public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/** The value is used for character storage. */private final char value[];//。。。。。。。。。。。。。。。。。。
}

String类被声明为final,这意味着它不能被继承。那么他里面的方法就是没办法被覆盖的。
用final修饰字符串内容的char[] (从JDK 1.9开始,char[]变成了byte[]),由于该数组被声明为final,一旦数组被初始化,就不能再指向其他数组
String类没有提供用于修改字符串内容的公共方法。例如,没有提供用于追加、删除或修改字符的方法。如果需要对字符串进行修改,会创建一个新的String对象。所以说String是不可变的。

与String不同StringBuilder和StringBuffer底层封装的char[]并没有用final修饰,这意味着它是可以修改的。

StringBuilder部分源码

public final class StringBuilderextends AbstractStringBuilderimplements Serializable, CharSequence
{//。。。。。。。。。。。。。。。。。
}
abstract class AbstractStringBuilder implements Appendable, CharSequence {/*** The value is used for character storage.*/char[] value;//。。。。。。。。。。。。。
}

StringBuffer部分源码

public final class StringBufferextends AbstractStringBuilderimplements Serializable, CharSequence
{//。。。。。。。。。。。。。。。。
}
abstract class AbstractStringBuilder implements Appendable, CharSequence {/*** The value is used for character storage.*/char[] value;//。。。。。。。。。。。。。。。。。。。。。。。
}

StringBuffer为何线程安全的,而StringBuilder为何非线程安全

StringBuffer是线程安全的,它的方法都使用了synchronized关键字进行同步。在每个方法内部,通过加锁(synchronized)来确保在多线程环境下的安全访问。这意味着当一个线程访问StringBuffer的方法时,其他线程需要等待锁释放后才能执行相应的方法。因此,StringBuffer适用于多线程环境下对字符串的修改操作。

    //StringBuffer部分源码@Overridepublic synchronized StringBuffer append(Object obj) {toStringCache = null;super.append(String.valueOf(obj));return this;}@Overridepublic synchronized StringBuffer append(String str) {toStringCache = null;super.append(str);return this;}

而StringBuilder则没有使用synchronized关键字进行同步,它是非线程安全的。这样可以提高性能,因为不需要进行锁的获取和释放操作。但是,在多线程环境下,如果有多个线程同时访问和修改StringBuilder对象,可能会导致数据不一致或出现竞态条件的问题。因此,StringBuilder适用于单线程环境下对字符串的修改操作。

    //StringBuilder部分源码@Overridepublic StringBuilder append(Object obj) {return append(String.valueOf(obj));}@Overridepublic StringBuilder append(String str) {super.append(str);return this;}

三者性能分析

String:由于String是不可变的,每次对String进行修改操作时,都会创建一个新的String对象。这可能导致频繁的对象创建和垃圾回收,影响性能

StringBuilder:由于StringBuilder是可变的,它使用可变的字符数组存储字符串,不会每次都创建新的对象。在需要频繁进行字符串拼接、替换等操作时,使用StringBuilder可以提高性能

StringBuffer:与StringBuilder类似,StringBuffer也是可变的,但是它是线程安全的。在多线程环境下,由于同步机制的存在,StringBuffer的性能可能会稍低于StringBuilder

使用场景

String:适用于不需要频繁修改字符串内容的场景。由于String是不可变的,每次对String进行拼接、替换或者修改操作时,都会创建一个新的String对象,这样可能会导致频繁的对象创建和垃圾回收,影响性能。因此,如果字符串内容不需要改变,或者只需要读取字符串的值,可以使用String。

  1. 对于一些常量字符串或者字面量,例如日志输出时的提示信息、固定格式的输出等,由于它们的值是固定的,不需要做任何修改,因此可以使用String。

  2. 在某些业务逻辑中,需要对字符串进行一些操作,但这些操作的结果不会影响原始字符串。例如,从数据库中查询到的数据如果需要展示给用户,通常不会被修改,这种场景下可以使用String。

StringBuilder:适用于单线程环境下需要频繁修改字符串的场景。由于StringBuilder是可变的,它使用可变的字符数组存储字符串,不会每次都创建新的对象。因此,在需要频繁进行字符串拼接、替换等操作时,使用StringBuilder可以提高性能。

  1. 在开发Web应用时,需要将多个字符串拼接成一个完整的HTML页面,这种场景下可以使用StringBuilder。

  2. 当需要从文件中读取数据,并进行一系列复杂的字符串操作时,可以使用StringBuilder。

StringBuffer:适用于多线程环境下需要频繁修改字符串的场景。与StringBuilder类似,StringBuffer也是可变的,但是它是线程安全的,内部的方法都使用了synchronized关键字进行同步。这意味着在多线程环境下,多个线程可以安全地同时访问和修改StringBuffer对象。因此,如果在多线程环境下需要频繁进行字符串操作,应该使用StringBuffer来确保线程安全。

  1. Web服务器需要同时处理多个客户端请求,这种场景下可以使用StringBuffer来确保线程安全。

  2. 一个多线程的任务,需要将多个线程的执行结果拼接成一个完整的字符串,可以使用StringBuffer。

相关文章:

  • Mysql(5日志备份恢复)
  • [Linux]Ubuntu noVNC使用
  • linux 休眠唤醒中设备、总线、用户进程、内核线程调试分析流程
  • arkts中@Watch监听的使用
  • [年终总结]人生就是大闹一场
  • 为什么不应该在 SAN/NAS 设备上运行 MinIO(还有一个例外)
  • 【机器学习】人工智能概述
  • Mysql 高级语句
  • P5729 【深基5.例7】工艺品制作题解
  • 数据资源将被视为资产 明天起纳入财务报表
  • 防火墙双机热备配置步骤
  • ubuntu22.04 安装jdk8,jdk11,jdk17,jdk21 并且便于切换
  • Springcloud Alibaba使用Canal将Mysql数据实时同步到Redis保证缓存的一致性
  • 继续声明 | 连声明都抄,谁抄袭谁,一目了然,现在竟然恬不知耻的反咬一口。
  • c语言实现得到某数的某方(n^k)的值
  • 收藏网友的 源程序下载网
  • 【EOS】Cleos基础
  • 【刷算法】从上往下打印二叉树
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • AngularJS指令开发(1)——参数详解
  • DataBase in Android
  • Java 网络编程(2):UDP 的使用
  • MySQL用户中的%到底包不包括localhost?
  • Promise面试题,控制异步流程
  • ReactNativeweexDeviceOne对比
  • webgl (原生)基础入门指南【一】
  • win10下安装mysql5.7
  • 规范化安全开发 KOA 手脚架
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 使用权重正则化较少模型过拟合
  • 通信类
  • 运行时添加log4j2的appender
  • Hibernate主键生成策略及选择
  • Java性能优化之JVM GC(垃圾回收机制)
  • 第二十章:异步和文件I/O.(二十三)
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • #[Composer学习笔记]Part1:安装composer并通过composer创建一个项目
  • #知识分享#笔记#学习方法
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (C语言)字符分类函数
  • (delphi11最新学习资料) Object Pascal 学习笔记---第2章第五节(日期和时间)
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (算法)Travel Information Center
  • (译)计算距离、方位和更多经纬度之间的点
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • (自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .NET delegate 委托 、 Event 事件
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON