【Java基础】深入理解String、StringBuffer和StringBuilder的异同

news2024/11/17 7:30:49

文章目录

    • 一、结论:
    • 二、可变性
      • String(不可变)
      • StringBuffer和StringBuilder(可变)
    • 三、线程安全性
      • String(线程安全)
      • StringBuffer(线程安全)和StringBuilder(线程不安全)
    • 四、性能
      • String(性能差)
      • StringBuffer(针对多线程)和StringBuilder(针对单线程)

一、结论:

String、StringBuffer和StringBuilder是Java中用于处理字符串的类,它们之间的区别主要体现在以下几个方面:

可变性String类是不可变的,一旦创建就不能修改,每次对字符串的操作都会创建新的字符串对象。而StringBuffer和StringBuilder类是可变的,可以在原字符串的基础上进行插入、删除和修改等操作。

线程安全性String类是线程安全的,因为它的不可变性使得多个线程不能同时修改同一个字符串对象。而StringBuffer类是线程安全的,所有方法都使用了synchronized关键字进行同步,可以在多线程环境下安全使用。而StringBuilder类是非线程安全的,没有进行同步处理,适用于单线程环境。

性能:由于String类的不可变性,每次对字符串进行修改操作都会创建新的字符串对象,会造成额外的内存开销。而StringBuffer和StringBuilder类支持原地修改字符串,避免了频繁创建对象的开销,因此在需要频繁进行字符串操作的场景下,StringBuffer和StringBuilder比String具有更好的性能。

一般来说,如果在单线程环境下进行字符串操作,且不需要频繁修改字符串内容,可以使用String类。如果在多线程环境下需要频繁修改字符串内容,并且要求线程安全,可以使用StringBuffer类。如果在单线程环境下需要频繁修改字符串内容,并且不要求线程安全,可以使用StringBuilder类以获得更好的性能。

以下将根据源码、对象创建多方面展示String、StringBuffer和StringBuilder的异同

可变性线程是否安全性能
String不可变线程安全最差,频繁修改String会创建大量垃圾对象
StringBuffer可变线程安全效率适中,因为方法加了synchronized,性能不是很好,但是保证了线程安全
StringBuilder可变线程不安全性能最好,但不保证线程安全

二、可变性

String(不可变)

String实例化的两种方式:
在这里插入图片描述
跟进String类看源码:
在这里插入图片描述
所以不管哪一种实例化的方式,所定义的字符串都会存在 value数组中,并且该字符数组被final关键字修饰,代表一旦赋值了,就不能修改了,也就代表了String类是不可变的

StringBuffer和StringBuilder(可变)

创建StringBuffer(或StringBuilder)对象,底层默认会创建一个长度为16的char数组
在这里插入图片描述在这里插入图片描述
StringBuffer、StringBuilder和String类似,底层也是用一个数组来存储字符串的值,并且数组的默认长度为16,即一个空的StringBuffer对象数组长度为16。实例化一个StringBuffer对象即创建了一个大小为16个字符的字符串缓冲区。但是​当我们调用有参构造函数创建一个StringBuffer对象时,数组长度就不再是16了,而是根据当前对象的值来决定数组的长度,数组的长度为“当前对象的值的长+16”。所以一个 StringBuffer 创建完成之后,有16个字符的空间可以对其值进行修改。如果修改的值范围超出了16个字符,会先检查StringBuffer对象的原char数组的容量能不能装下新的字符串,如果装不下则会对 char 数组进行扩容。

那StringBuffer是怎样进行扩容的呢?
扩容的逻辑就是创建一个新的 char 数组,将现有容量扩大一倍再加上2,如果还是不够大则直接等于需要的容量大小。扩容完成之后,将原数组的内容复制到新数组,最后将指针指向新的 char 数组。
说明用StringBuffer和StringBuilder创建的字符串对象的长度是可以动态可变的

三、线程安全性

String(线程安全)

实际上,String类是不可变的,因此它是线程安全的。多个线程可以同时读取String对象的值,而无需担心数据的一致性问题。

由于String类的不可变性,每次对字符串进行修改操作都会创建新的字符串对象,这意味着在频繁修改字符串的情况下可能会产生大量的临时对象,从而导致内存消耗较大。但是这并不涉及到线程安全性的问题。

StringBuffer(线程安全)和StringBuilder(线程不安全)

StringBuffer线程安全最大的体现就是在所有的方法体上加上了synchronized关键字
在这里插入图片描述
所以是线程安全的
相反StringBuilder的方法体上没有synchronized关键字,所以他是线程不安全的

四、性能

String(性能差)

由于String类的不可变性,每次对字符串进行修改操作都会创建新的字符串对象,会造成额外的内存开销。

StringBuffer(针对多线程)和StringBuilder(针对单线程)

  • StringBuffer和StringBuilder类支持原地修改字符串,避免了频繁创建对象的开销,因此在需要频繁进行字符串操作的场景下,StringBuffer和StringBuilder比String具有更好的性能。
  • 并且StringBuffer几乎所有的方法都使用synchronized实现了同步,线程比较安全,在多线程系统中可以保证数据同步,但是效率比较低;而StringBuilder 没有实现同步,线程不安全,在多线程系统中不能使用 StringBuilder,但是效率比较高。
  • 如果我们在实际开发过程中需要对字符串进行频繁的修改,不要使用String,否则会造成内存空间的浪费;当需要考虑线程安全的场景下使用 StringBuffer,如果不需要考虑线程安全,追求效率的场景下可以使用 StringBuilder。

详细请参考,总结的很详细到位深入理解String、StringBuffer和StringBuilder:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/899528.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

58.C++ STL标准模板库 STL概述 STL三大组件

一、初识STL 1.1 STL概述 长久以来,软件界⼀直希望建⽴⼀种可重复利⽤的东⻄,以及⼀种得以制造出”可重复运⽤的东⻄”的⽅法,让程序员的⼼⾎不⽌于随时间的迁移,⼈事异动⽽烟消云散,从函(functions),类别(classes),函…

nginx 配置反向代理的逻辑原则案例(值得一看)

一 实操步骤 1.1 架构图 1.2 配置原则 匹配准则: 当proxy_pass代理地址端口后有目录(包括 / 和/xxx),相当于是绝对根路径,则 nginx 不会把 location 中匹配的路径部分代理走; 当proxy_pass代理地址端口后无任何内容,可以理解为相对路径…

matlab使用教程(19)—曲线拟合与一元方程求根

1.多项式曲线拟合 此示例说明如何使用 polyfit 函数将多项式曲线与一组数据点拟合。您可以按照以下语法,使用 polyfit 求出以最小二乘方式与一组数据拟合的多项式的系数 p polyfit(x,y,n), 其中: • x 和 y 是包含数据点的 x 和 y 坐标的向量 …

DP读书:鲲鹏处理器 架构与编程(七)ARMv8-A 体系结构

一小时速通ARMv8-A体系结构 一、ARMv8-A处理单元核心架构1. ARMv8-A架构的处理器运行模式a. ARMv8-A的执行架构A. AArch64 执行状态B. AArch32 执行状态 b. ARMv8-A架构支持的指令集c. ARMv8-A 支持的数据类型d. ARMv8-A 的异常等级与安全模型e. ARMv8-A的虚拟化架构f. ARMv8-A…

Vue项目商品购物车前端本地缓存逻辑(适用H5/ipad/PC端)——前端实现购物车删除商品、购物车增减数量,清空购物车功能

一、需求 1、用户选择商品,自动回显在购物车列表中; 2、同个商品追加,购物车列表数量叠加; 3、开启赠送,选中的商品,在购物车中另增一条数据,且购物车列表价格显示为0;其实际价格在…

【OpenVINOSharp】在英特尔® 开发者套件爱克斯开发板使用OpenVinoSharp部署Yolov8模型

在英特尔 开发者套件爱克斯开发板使用OpenVinoSharp部署Yolov8模型 一、英特尔开发套件 AIxBoard 介绍1. 产品定位2. 产品参数3. AI推理单元 二、配置 .NET 环境1. 添加 Microsoft 包存储库2. 安装 SDK3. 测试安装4. 测试控制台项目 三、安装 OpenVINO Runtime1. 下载 OpenVINO…

【无闪烁AI视频制作】

效果查看: https://tianfeng.space/wp-content/uploads/2023/08/8月16日-12.mp4 前言 现在其实有很多的AI视频了,效果也越来越逼真,来看看都是怎么制作的吧! 安装 TemporalKit下载 https://github.com/CiaraStrawberry/Tempo…

STM32 F103C8T6学习笔记9:0.96寸单色OLED显示屏—自由取模显示—显示汉字与图片

今日学习0.96寸单色OLED显示屏的自由取模显示: 宋体汉字比较复杂,常用字符可以直接复制存下来,毕竟只有那么几十个字母字符,但汉字实在太多了,基本不会全部放在单片机里存着,一般用到多少个字就取几个字的模&#xff…

操作系统_内存管理(一)

目录 1. 内存管理 1.1 内存管理的概念 1.1.1 内存管理的基本原理和要求 1.1.1.1 程序的链接和装入 1.1.1.2 逻辑地址与物理地址 1.1.1.3 进程的内存映像 1.1.1.4 内存保护 1.1.1.5 内存共享 1.1.1.6 内存分配与回收 1.2 覆盖与交换 1.2.1 覆盖 1.2.2 交换 1.3 连续…

华为认证为什么现在这么受欢迎?

华为认证目前受欢迎的原因有很多,以下是其中一些主要原因: 高质量的认证培训:华为认证提供了一系列高质量的培训课程,涵盖了IT技术、网络安全、云计算等领域。这些培训课程由华为的技术专家和工程师团队设计和提供,内容…

Openlayers 实战 - 地图视野(View)- 图层 -(layer)- 资源(source)显示等级设置

Openlayers 实战 - 地图视野(View)- 图层 -(layer)- 资源(source)显示等级设置 问题原因核心代码完整代码:在线示例 在以往的项目维护中,出现一个问题,使用最新高清底图发…

基于traccar快捷搭建gps轨迹应用

0. 环境 - win10 虚拟机ubuntu18 - i5 ubuntu22笔记本 - USB-GPS模块一台,比如华大北斗TAU1312-232板 - 双笔记本组网设备:路由器,使得win10笔记本ip:192.168.123.x,而i5笔记本IP是192.168.123.215。 - 安卓 手机 1.…

PHP酒店点菜管理系统mysql数据库web结构apache计算机软件工程网页wamp

一、源码特点 PHP 酒店点菜管理系统是一套完善的web设计系统,对理解php编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 代码下载 https://download.csdn.net/download/qq_41221322/88232051 论文 https://…

ARM体系结构学习笔记:NZCV

NZCV N: negative 算术逻辑运算单元运算结果为负1/正0 Z: zero 算术逻辑运算单元运算结果为零1/非零0 C: 3cases:1 0加法 Carray | Not Carray减法 Not Borrow | Borrow(Not Carray)移位 Bit Shifted | Rotated Out V: 后面详细阐述[外…

【C语言】数组概述

🚩纸上得来终觉浅, 绝知此事要躬行。 🌟主页:June-Frost 🚀专栏:C语言 🔥该篇将带你了解 一维数组,二维数组等相关知识。 目录: 📘前言:&#x1f…

【探索Linux】—— 强大的命令行工具 P.6(调试器-gdb、项目自动化构建工具-make/Makefile)

阅读导航 前言一、什么是调试器二、详解 GDB - 调试器1.使用前提2.经常使用的命令3.使用小技巧 三、项目自动化构建工具 - make/Makefile1. make命令⭕语法⭕常用选项⭕常用操作⭕make命令的工作原理⭕make命令的优势: 2.Makefile文件⭕Makefile的基本结构⭕Makefil…

jvm-运行时数据区概述及线程

1.运行时数据区内部结构 不同的jvm对于内存的划分方式和管理机制存在着部分差异 java虚拟机定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机的启动而创建,随着虚拟机的退出而销毁,另外一些则是与线程一一对应的&…

过来,我告诉你个秘密:送给程序员男友最好的礼物,快教你对象学习磁盘分区啦!小点声哈,别让其他人学会了!

[原文连接:来自给点知识](过来,我告诉你个秘密:送给程序员男友最好的礼物,快教你对象学习磁盘分区啦!小点声哈,别让其他人学会了!) 再唱不出那样的歌曲 听到都会红着脸躲避 虽然会经常忘了我依然爱着你 …

linux学习(文件描述符)[13]

所以fork的时候函数执行完毕,但是数据还在缓冲区中未刷新。 所以会有父子两份数据 在fork()之前ffush()(c语言的接口,刷新缓冲区)fflush(stdout),就不会有重复 缓冲区的…

公网远程连接Redis数据库详解

文章目录 1. Linux(centos8)安装redis数据库2. 配置redis数据库3. 内网穿透3.1 安装cpolar内网穿透3.2 创建隧道映射本地端口 4. 配置固定TCP端口地址4.1 保留一个固定tcp地址4.2 配置固定TCP地址4.3 使用固定的tcp地址连接 前言 洁洁的个人主页 我就问你有没有发挥&#xff0…