一文简单回顾Java中的String、StringBuilder、StringBuffer

简单说下String、StringBuilder、StringBuffer的区别

  • String、StringBuffer、StringBuilder在Java中都是用于处理字符串的,它们之间的区别是String是不可变的,平常开发用的最多,当遇到大量字符串连接的时候,就用StringBuilder,它不会生成很多新的对象,StringBuffer和StringBuilder类似,但每个方法上都加了synchronized 关键字,所以是线程安全的;

接下来说下String的特点

  • String类的对象是不可变的,也就是说,一旦一个String对象被创建,它所包含的字符串内容是不可改变的;
  • 每次对String对象进行修改操作,比如拼接、替换等操作时,实际上都会生成一个新的String对象,而不是修改原有对象。这可能会导致内存和性能开销,尤其是在大量字符串操作的情况下;

继续说下StringBuilder的特点

  • StringBuilder提供了一系列的方法来进行字符串的增删改查操作,这些操作都是直接在原有字符串对象的底层数组上进行的,而不是生成新的String对象;
  • StringBuilder不是线程安全的。这意味着在没有外部同步的情况下,它不适用于多线程环境;
  • 相比于String,在进行频繁的字符串修改操作时,StringBuilder能提供更好的性能。Java中的字符串连+操作其实就是通过StringBuilder实现的;

StringBuffer的特点

  • StringBuffer和StringBuidler类似,但StringBuffer是线程安全的,方法前面都加了synchronized关键字;

总结下三者的使用场景

  • String:适用于字符串内容不会改变的场景,比如说作为HashMap的key
  • StringBuilder:适用于单线程环境下需要频繁修改字符串内容的场景,比如在循环中拼接或修改字符串,是String的完美替代品
  • StringBuffer:现在不怎么用了,因为一般不会在多线程场景下去频繁的修改字符串内容;

延申问下String是不可变类吗?字符串拼接是如何实现的?

  • String是不可变的,这意味着一旦一个String对象被创建,其存储的文本内容就不能被改变。这是因为:
    1. 不可变性使得String对象在使用中更加安全,因为字符串经常用作参数传递给其他Java方法,例如网络连接、打开文件等
      如果String是可变的,这些方法调用的参数值就可能在不知不觉中被改变,从而导致网络连接被篡改,文件被莫名奇妙地修改等问题
    2. 不可变的对象因为状态不会改变,所以更容易进行缓存和重用。字符串常量池的出现正是基于这个原因;
      当代码中出现相同的字符串字面量时,JVM会确保所有的引用都指向常量池中的同一个对象,从而节约内存;
    3. 因为String的内容不会变,所以它的哈希值也就固定不变。这使得String对象特别适合作为HashMap或HashSet等集合的键,因为计算哈希值只需要进行一次,提高了哈希操作的效率;

接下来回答第二个问题,字符串是如何实现的呢?

  • 例如String是不可变的,因此通过“+”操作符进行的字符串拼接,会生成新的字符串对象。
String a = "hello ";
String b = "world!";
String ab = a + b;
  • a 和 b 是通过双引号定义的,所以会在字符串常量池中,而 ab 是通过“+”操作符拼接的,所以会在堆中生成一个新的对象。

在这里插入图片描述

Java 8 时,JDK 对“+”号的字符串拼接进行了优化,Java 会在编译期基于 StringBuilder 的 append 方法进行拼接。
上面的代码相当于:

String a = "hello ";
String b = "world!";
StringBuilder sb = new StringBuilder();
sb.append(a);
sb.append(b);
String ab = sb.toString();

因此,如果笼统地讲,通过加号拼接字符串时会创建多个 String 对象是不准确的。因为加号拼接在编译期还会创建一个 StringBuilder 对象,最终调用 toString() 方法的时候再返回一个新的 String 对象。

@Override
public String toString() {// Create a copy, don't share the arrayreturn new String(value, 0, count);
}

那除了使用 + 号来拼接字符串,还有 StringBuilder.append()String.join() 等方式。

还想问下,如何保证String不可变呢?

  1. String内部类使用一个私有的字符数组来存储字符串数据。这个字符数组在创建字符串时被初始化,之后不允许被修改

    private final char value[];
    
  2. String类没有提供任何可以修改其内容的公共方法,像concat这些看似修改字符串的操作,实际上都是返回一个新创建的字符串对象,而原始字符串对象保持不变

    public String concat(String str) {if (str.isEmpty()) {return this;}int len = value.length;int otherLen = str.length();char buf[] = Arrays.copyOf(value, len + otherLen);str.getChars(buf, len);return new String(buf, true);
    }
    
  3. String类本身被声明为final,这意味着它不能被继承。这防止了子类可能通过添加修改方法来改变字符串内容的可能性;

    public  final class String
    

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对游戏宣发的粗浅思考

1.两极分化 认真观摩了mgs系列制作人的x账号, 其更新频率吓死人,一天能发几十条之多,吓死人。大部分都是转发相关账号的ds2或mgs相关内容, 每日刻意的供给这些内容来满足几十万粉丝需求,维护热情。 幕后是专业的公…

【数据结构】空间复杂度

目录 一、引入空间复杂度的原因 二、空间复杂度的分析 ❥ 2.1 程序运行时内存大小 ~ 程序本身大小 ❥ 2.2 程序运行时内存大小 ~ 算法运行时内存大小 ❥ 2.3 算法运行时内存大小 ❥ 2.4 不考虑算法全部运行空间的原因 三、空间复杂度 ❥ 3.1空间复杂度的定义 ❥ 3.2 空…

实践网络安全:常见威胁与应对策略详解

📝个人主页🌹:一ge科研小菜鸡-CSDN博客 🌹🌹期待您的关注 🌹🌹 引言 在数字化转型的浪潮中,网络安全的重要性已达到前所未有的高度。无论是个人用户、企业,还是政府机构…

Tensor 基本操作2 理解 tensor.max 操作,沿着给定的 dim 是什么意思 | PyTorch 深度学习实战

前一篇文章,Tensor 基本操作1 | PyTorch 深度学习实战 本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started 目录 Tensor 基本操作torch.max默认指定维度 Tensor 基本操作 torch.max torch.max 实现降维运算,基于指定的 d…

图像处理之HSV颜色空间

目录 1 RGB 的局限性 2 HSV 颜色空间 3 RGB与HSV相互转换 4 HSV颜色模型对图像的色相、饱和度和明度进行调节 5 演示Demo 5.1 开发环境 5.2 功能介绍 5.3 下载地址 参考 1 RGB 的局限性 RGB 是我们接触最多的颜色空间,由三个通道表示一幅图像,分…

数据结构题目 课时9

题目 1、任何一个带权的无向连通图的最小生成树( )。 A. 只有一棵 B. 有一棵或多棵 C. 一定有多棵 D. 可能不存在 2、一个赋权网络如下图所示。从顶点 a 开始,用 Prim 算法求出一棵最小生成树。 3、请对下图的无向带权图按克鲁斯卡尔算法求…

Linux之详谈——权限管理

目录 小 峰 编 程 ​编辑 一、权限概述 1、什么是权限 2、为什么要设置权限 3、Linux中的权限类别- 4、Linux中文件所有者 1)所有者分类(谁) 2)所有者的表示方法 ① u(the user who owns it)(属主权限&…

私有包上传maven私有仓库nexus-2.9.2

一、上传 二、获取相应文件 三、最后修改自己的pom文件

记录 | 基于Docker Desktop的MaxKB安装

目录 前言一、MaxKBStep 1Step2 二、运行MaxKB更新时间 前言 参考文章:如何利用智谱全模态免费模型,生成大家都喜欢的图、文、视并茂的文章! MaxKB的Github下载地址 参考视频:【2025最新MaxKB教程】10分钟学会一键部署本地私人专属…

4.flask-SQLAlchemy,表Model定义、增删查改操作

介绍 SQLAlchemy是对数据库的一个抽象 开发者不用直接与SQL语句打交道 Python对象来操作数据库 SQLAlchemy是一个关系型数据库 安装 flask中SQLAlchemy的配置 from flask import Flask from demo.user_oper import userdef create_app():app Flask(__name__)# 使用sessi…

jemalloc 5.3.0的tsd模块的源码分析

一、背景 在主流的内存库里,jemalloc作为android 5.0-android 10.0的默认分配器肯定占用了非常重要的一席之地。jemalloc的低版本和高版本之间的差异特别大,低版本的诸多网上整理的总结,无论是在概念上和还是在结构体命名上在新版本中很多都…

【Elasticsearch】Elasticsearch的查询

Elasticsearch的查询 DSL查询基础语句叶子查询全文检索查询matchmulti_match 精确查询termrange 复合查询算分函数查询bool查询 排序分页基础分页深度分页 高亮高亮原理实现高亮 RestClient查询基础查询叶子查询复合查询排序和分页高亮 数据聚合DSL实现聚合Bucket聚合带条件聚合…

DeepSeek R1有什么不同

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

macbook安装go语言

通过brew来安装go语言 使用brew命令时,一般都会通过brew search看看有哪些版本 brew search go执行后,返回了一堆内容,最下方展示 If you meant "go" specifically: It was migrated from homebrew/cask to homebrew/core. Cas…

文本左右对齐

hello 大家好!今天开写一个新章节,每一天一道算法题。让我们一起来学习算法思维吧! function fullJustify(words, maxWidth) {// 用于存储最终排版好的每一行文本const result [];// 用于遍历单词数组的索引,初始化为 0let i 0;…

Oracle 创建用户和表空间

Oracle 创建用户和表空间 使用sys 账户登录 建立临时表空间 --建立临时表空间 CREATE TEMPORARY TABLESPACE TEMP_POS --创建名为TEMP_POS的临时表空间 TEMPFILE /oracle/oradata/POS/TEMP_POS.DBF -- 临时文件 SIZE 50M -- 其初始大小为50M AUTOEXTEND ON -- 支持…

树状数组讲解

文章目录 1395.统计作战单位数 树状数组b站博主 灵神博主 tree数组:Tree[i] 存储的是原本的数组中num[i - (i&-i)1]到nums[i]的和 更新的时候,num[i[更新,逐一修改num[i(i & -i)] 307.区间和检索-数组可修改 题目实战 总的代码&#…

PostGIS笔记:PostgreSQL中表、键和索引的基础操作

创建、查看与删除表 在数据库中创建一个表,使用如下代码: create table streets (id serial not null primary key, name varchar(50));这里的表名是streets,id是主键所以非空,采用serial数据类型,这个数据类型会自动…

【JavaEE进阶】图书管理系统 - 壹

目录 🌲序言 🌴前端代码的引入 🎋约定前后端交互接口 🚩接口定义 🍃后端服务器代码实现 🚩登录接口 🚩图书列表接口 🎄前端代码实现 🚩登录页面 🚩…

大数据学习之SCALA分布式语言三

7.集合类 111.可变set一 112.可变set二 113.不可变MAP集合一 114.不可变MAP集合二 115.不可变MAP集合三 116.可变map一 package com . itbaizhan . chapter07 //TODO 2. 使用 mutable.Map 前导入如下包 import scala . collection . mutable // 可变 Map 集合 object Ma…