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

【从0开始学习Java | 第11篇】String、StringBuilder与StringBuffer

在这里插入图片描述

文章目录

  • 前言
  • 🥝基础定义与核心差异​
  • 🐦‍🔥底层实现与内存表现​
  • String字符串详解💡
    • 创建String字符串
    • String 类是不可改变的解析
    • String类的常用方法🧾
  • StringBuilder和StringBuffer详解
    • StringBuffer常用方法🧾
    • 示例
  • 🤔三种字符类型总结

前言

在 Java 中,字符串处理是日常开发中不可或缺的部分。而StringStringBuilderStringBuffer这三个类,更是频繁出现在各种代码场景中。它们看似相似,却在底层实现、性能表现和适用场景上有着天壤之别,让我们通过这篇文章深入了解。

🥝基础定义与核心差异​

要理解这三个类的区别,首先得从它们的定义和最核心的特性说起:

  • String类是 Java 中最基本的字符串表示形式,它被声明为final,这意味着它是不可变的。所谓不可变,就是指一旦String对象被创建,它所包含的字符序列就不能再被修改。每次对String进行拼接、截取等操作时,都会生成一个新的String对象,而原来的对象则会被丢弃,等待垃圾回收。​
  • StringBuilder和StringBuffer则是为了解决String不可变带来的性能问题而出现的。它们都继承自AbstractStringBuilder类,内部都维护着一个可变的字符数组,可以对字符序列进行动态修改。两者最大的区别在于线程安全性:StringBuffer中的大部分方法都被 synchronized关键字修饰,因此它是线程安全的;而StringBuilder没有进行线程同步处理,所以它是非线程安全的。

🐦‍🔥底层实现与内存表现​

深入了解它们的底层实现,能让我们更清晰地认识到为什么会存在这些差异:

  • String类内部使用一个char数组(JDK9 及以上改为byte数组,根据编码方式不同节省空间)来存储字符,并且这个数组被声明为final。这就从根本上保证了String对象的不可变性。当我们执行str = str + "world"这样的操作时,实际上是创建了一个新的String对象,将原来的str和"world"的字符序列复制到新的数组中,原来的str对象则失去了引用。​
  • StringBuilderStringBuffer的底层同样是一个字符数组,但这个数组没有被声明为final。它们通append、insert等方法直接对数组进行修改,当数组的容量不足时,会进行扩容操作 —— 创建一个更大的数组,将原来的字符序列复制过去,然后继续使用新的数组。这种方式避免了频繁创建新对象,大大提高了字符串操作的效率。​不过,StringBuffer由于需要保证线程安全,在每个方法上都添加了同步锁,这会导致一定的性能开销。在单线程环境下,StringBuilder的性能要优于StringBuffer

String字符串详解💡

创建String字符串

创建字符串最简单的方式如下:
String str = “Runoob”;
在代码中遇到字符串常量时,这里的值是 “Runoob”,编译器会使用该值创建一个 String 对象。
和其它对象一样,可以使用关键字和构造方法来创建 String 对象,用构造函数创建字符串:
String str2=new String(“Runoob”);

String 创建的字符串存储在公共池中,而 new 创建的字符串对象在堆上:

String s1 = "Runoob";              // String 直接创建
String s2 = "Runoob";              // String 直接创建
String s3 = s1;                    // 相同引用
String s4 = new String("Runoob");   // String 对象创建
String s5 = new String("Runoob");   // String 对象创建

该代码中的各个String在公共池和堆中的存在方式:
在这里插入图片描述

String 类是不可改变的解析

例如:

String s = "Google";
System.out.println("s = " + s);s = "Runoob";
System.out.println("s = " + s);

输出结果为:

Google
Runoob

从结果上看是改变了,但为什么说 String 对象是不可变的呢?

原因在于实例中的 s 只是一个 String 对象的引用,并不是对象本身,当执行 s = “Runoob”; 创建了一个新的对象 “Runoob”,而原来的 “Google” 还存在于内存中。
在这里插入图片描述

String类的常用方法🧾

方法说明
public int length()获取字符串的长度
public boolean equals(Object anObject)比较两个字符串是否相同
public boolean equalsIgnoreCase(String anotherString)忽略大小比较两个字符串是否相同
public String toLowerCase()转换为小写
public String toUpperCase()转换为大写
public int indexOf(int ch)获取指定字符在字符串中第一次出现的下标
public int lastIndexOf(int ch)获取指定字符在字符串中最后一次出现的下标
public int indexOf(String str)获取指定字符串在字符串中第一次出现的下标
public int lastIndexOf(String str)获取指定字符串在字符串中最后一次出现的下标
public char charAt(int index)获取字符串中的指定下标的字符
public String substring(int beginIndex)从指定开始位置截取字符串,直到字符串的末尾
public String substring(int beginIndex, int endIndex)从指定开始位置到指定结束位置截取字符串
public String concat(String str)将字符串追加到末尾

StringBuilder和StringBuffer详解

当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。

和 String 类不同的是,StringBufferStringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
在这里插入图片描述

在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使用 StringBuffer

StringBuffer常用方法🧾

public StringBuffer append(String s)将一个字符串添加到StringBuilder存储区
public StringBuilder append(StringBuffer sb)将StringBuffer存储的内容添加StringBuilder存储区
public StringBuffer reverse()将此字符序列用其反转形式取代
public delete(int start, int end)移除此序列的子字符串中的字符
public insert(int offset, int i)将 int 参数的字符串表示形式插入此序列中
insert(int offset, String str)将 str 参数的字符串插入此序列中。
replace(int start, int end, String str)使用给定 String 中的字符替换此序列的子字符串中的字符

示例

public class Test{public static void main(String[] args){StringBuilder sb = new StringBuilder(10);sb.append("Runoob..");System.out.println(sb);  sb.append("!");System.out.println(sb); sb.insert(8, "Java");System.out.println(sb); sb.delete(5,8);System.out.println(sb);  }
}

在这里插入图片描述

🤔三种字符类型总结

String 、 StringBuilder 和 StringBuffer 都是用来处理字符串的。在处理少量字符串的时候,它们之间的处理效率几乎没有任何区别
 但在处理大量字符串的时候,由于 String 类的对象不可再更改,因此在处理字符串时会产生新的对象,就算调用 String 的 concat 方法,那也是把字符串拼接起来并重新创建一个对象,把拼接后的 String 的值赋给新创建的对象,因此相比较于 StringBuffer,String 一旦发生长度变化,是非常耗费内存的,导致效率低下。
 而 StringBuilder和 StringBuffer 使用的是对字符串的字符数组内容进行拷贝,不会产生新的对象,因此效率较高,而StringBuffer 为了保证在多线程情况下字符数组中内容的正确使用,在每一个成员方法上面加了锁,有锁就会增加消耗,因此 StringBuffer 在处理效率上要略低于 StringBuilder


如果我的内容对你有帮助,请 点赞 评论 收藏 。创作不易,大家的支持就是我坚持下去的动力!
在这里插入图片描述

http://www.dtcms.com/a/309256.html

相关文章:

  • 微信小程序转Vue2组件智能提示词
  • 隧道安全监测哪种方式好?精选方案与自动化监测来对比!
  • 11.Layout-Pinia优化重复请求
  • C++赋值运算符重载
  • PHP Zip 文件操作详解
  • 汽车供应链PPAP自动化审核指南:如何用AI实现规则精准匹配与文件智能校验
  • MyBatis核心
  • MySQL——视图
  • C++对象访问有访问权限是不是在ide里有效
  • StarRocks vs. Trino
  • JavaWeb(苍穹外卖)--学习笔记16(定时任务工具Spring Task,Cron表达式)
  • RAGFLOW~Enable RAPTOR
  • 【云计算】云主机的亲和性策略(二):集群节点组
  • [ java 网络 ] TPC与UDP协议
  • 微波(Microwave)与毫米波(Millimeter wave)简介
  • 动态域名解析(DDNS)到底有什么用?
  • OSPF综合大实验
  • 下次接好运~
  • Oracle EBS 缺少adcfgclone.pl文件
  • 一分钟了解IO-Link 系列集线器
  • LaTeX 复杂图形绘制教程:从基础到进阶
  • Deep Height Decoupling for Precise Vision-based 3D Occupancy Prediction
  • 数据结构前篇 - 深入解析数据结构之复杂度
  • Leetcode——53. 最大子数组和
  • 如何将消息转移到新 iPhone
  • 如何将联系人从三星手机转移到 iPhone
  • MySQL 高并发下如何保证事务提交的绝对顺序?
  • 转换图(State Transition Diagram)和时序图(Sequence Diagram)画图流程图工具
  • 新手向:国内外大模型体验与评测
  • 智能图书馆管理系统开发实战系列(四):后端C++ DLL开发与模块化设计