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

Java基础:String、StringBuilder 和 StringBufferr对比

目录

基础用法

1.String

2.StringBuilder和StringBufferr

略微深入

1.为什么StringBuiler线程不安全

2.为什么StringBuffer线程安全


基础用法

1.String

在Java中,String是不可变类。

所以new一个String对象之后,它的值是不可变的。对它的修改,实际上是生成新对象。

例如:

public class StringExample { public static void main(String[] args) { String str1 = "Hello"; String str2 = str1.concat(", World!"); System.out.println(str1); // 输出:Hello System.out.println(str2); // 输出:Hello, World! } }

2.StringBuilder和StringBufferr

二者都是可变类,也就是能在不生成新对象的情况下修改字符串。单纯从使用角度来看是差不多的

例如:

public class StringBuilderExample { public static void main(String[] args) { StringBuilder sb = new StringBuilder("Hello"); sb.append(", World!"); System.out.println(sb.toString()); // 输出:Hello, World! } }

略微深入

三者之间的区别很直观,如下表所示。接下来主要基于具体问题,深入源码分析

1.为什么StringBuiler线程不安全

StringBuilder 和 StringBuffer,二者都继承父类 AbstractStringBuilder。

对象内部核心就两个成员:

char[] value; // 真正存放字符的数组 int count; // 记录数组里实际存了多少个有效字符

StringBuilder中的append,直接调用父类:

@Override public StringBuilder append(String str) { // 直接调用父类 AbstractStringBuilder 的append super.append(str); return this; }

再看父类append方法源码:

public AbstractStringBuilder append(String str) { if (str == null) return appendNull(); int len = str.length(); ensureCapacityInternal(count + len);// 校验容量,不够就翻倍扩容 str.getChars(0, len, value, count);// 把字符串字符拼进去,从count位置开始写入 count += len; // 计数器自增 return this; }

重点关注计数器自增操作,这也是导致线程不安全的原因:

问题 1:count += len 非原子操作
count += len 会拆分成 3 步 CPU 指令:
读取 count 当前值;
执行加法运算;
将结果写回 count 变量。
如果多线程同时执行:
线程 A、线程 B 读到同一个 count 值,加法完成后先后写回,后写入的值会覆盖前一个,最终 count 偏小,字符丢失。

问题 2:ensureCapacityInternal 并发判断产生越界
线程 A、线程 B 同时判断,都认为容量充足,不触发扩容。
此时线程 A先拼接,线程B后拼接,一起拼进去长度可能就超出数组范围了,会抛出 ArrayIndexOutOfBoundsException。

2.为什么StringBuffer线程安全

看StringBuffer的append方法:

@Override public synchronized StringBuffer append(String str) { super.append(str); return this; }

好像和StringBuilder差不多?

关键点在于多了synchronized修饰:

synchronized是 Java 内置的悲观锁,JVM 层面实现,用来保证多线程并发下:
原子性:代码块一次性执行完毕,不会被线程打断
可见性:一个线程修改变量,其他线程立刻可见
有序性:禁止指令重排

自然也就不会出现和StringBuilder一样的问题,因为多个线程访问同一个对象的同一方法会互斥。

http://www.jsqmd.com/news/1079948/

相关文章:

  • 主流操作系统大盘点:从桌面到移动
  • 封装统计接口的开始时间和请求时间StatisticsQuery
  • 告别复杂命令行:3步轻松掌握Android设备图形化管理
  • NL2SQL落地企业遇阻?语义映射与查询验证是破局关键
  • Bebas Neue字体完全指南:从零开始掌握专业标题设计的5个关键步骤
  • OSXPhotos:macOS 照片库的全能管理工具
  • 客户看到的不是企业本身,而是企业表达出来的样子
  • MAX6675 Arduino库实战指南:如何解决高温测量中的三大痛点
  • 计算机毕业设计之基于SSM的拍客网的设计与实现
  • 2026美发店收银系统越用越卡:技术根因分析与选型指南
  • 模块化缠论量化框架:从理论到实践的技术实现深度解析
  • 从寄存器角度理解 Type-C 上电与下电:两种控制方式解析
  • 服务可靠性设计指南
  • Llama 3-8B本地微调实战:QLoRA+Ollama零基础部署指南
  • 从一次性 Prompt 到连续工作流:投研 Agent 为什么需要长期可用的数据入口?
  • 招投标信息平台怎么选?评估阶段必看:官方、综合、垂直三类平台全解析
  • 如何快速上手RedNotebook:新手完整日记管理指南
  • 光通信APT相关的参考文献推荐
  • openYuanrong frontend:云原生函数网关的终极解决方案 [特殊字符]
  • 移动优先时代:本地GEO优化的移动端适配技巧
  • MCP16311/2峰值电流模式与PFM/PWM混合控制原理与设计实战
  • 跟单员工作重复性太强,未来怎么办?2026年职业转型新思路
  • 机器人激光雷达全生命周期成本分析:从采购到维护的隐藏账单
  • 算子代数视角:用谱复杂性解析Navier-Stokes方程与湍流本质
  • 【软工方法论35】SpringBoot核心原理与实践
  • 盘点2026鼠标推荐性价比高的产品:迈从产品手感与性能兼具成优选
  • 零壹教育:数据结构选型避坑指南
  • 如何快速上手轻舟Qingzhou?5分钟搭建你的第一个Web管理应用
  • 【 ArcGIS Pro 3.7新增功能6】ArcGIS Pro终于支持转换个人地理数据库.mdb!国土等多行业“旧数据”可以直接转换!
  • 端侧 AI 落地避坑指南(中):为什么 QAT 救不了精度?——对齐“融合后算子“的硬件物理约束