java中的String类、StringBuffer类、StringBuilder类的详细讲解(包含相互之间的比较)

news2025/1/23 6:34:57

文章目录

  • 一、String 类
    • 1 String 类的介绍
    • 2 String 对象创建的两种方式
    • 3 测试题加深理解
      • (1) 例题一
      • (2)例题二
      • (3) 例题三
    • 4 String 类的常用方法
      • (1)`equals()`
      • (2)`equalsIgnoreCase()`
      • (3)`length()`
      • (4)`indexOf()`
      • (5)`lastIndexOf()`
      • (6)`substring()`
      • (7)`trim()`
      • (8)`charAt()`
      • (9)`toUpperCase()`
      • (10)`toLowerCase()`
      • (11)`concat()`
      • (12)`replace()`
      • (13)`split()`
      • (14)`compareTo()`
        • 1. 逐字符比较:
        • 2. 长度比较:
        • 总结:
      • (15)`toCharArray()`
      • (16)`format()`
  • 二、StringBuffer 类
    • 1 基本介绍
    • 2 String 和 StringBuffer 相互转换
    • 3 StringBuffer 类的常用方法
      • (1)增: `append()`
      • (2)删: `delete()`
      • (3)`replace()`
      • (4)`indexOf()`
      • (5)`insert()`
      • (6)`length()`
  • 三、StringBuilder 类
    • 1 基本介绍
    • 2 StringBuilder 的方法和 StringBuffer 是一样的。
    • 3 String、StringBuffer 和 StringBuilder 的比较
  • 四 、String、StringBuffer 和 StringBuilder 的选择

一、String 类

1 String 类的介绍

  1. String 对象用于保存字符串,也就是一组字符序列。
  2. 字符串常量对象是用双引号括起来的字符序列。例如:“这是字符串” 、“1234” 等。
  3. 字符串的字符使用 Unicode 字符编码,一个字符(不区分字母还是汉字)占两个字节。
  4. String 类较常用构造器:
    • String s1 = new String();
    • String s2 = new String(String original);
    • String s3 = new String(char[] a);
    • String s4 = new String(char[] a, int startIndex, int count);

image-20250122140701639

  1. String 类的继承和实现关系:
    • CharSequence 接口:表示一系列可读的 char 值。它提供了对多种不同类型的 char 序列的统一、只读访问。这个接口的主要实现类包括 CharBufferStringStringBufferStringBuilder
    • Comparable 接口:在Java编程中,Comparable接口是实现对象排序的一种方式。它定义了对象的自然顺序,使得对象可以根据其内在特征进行排序。例如,整数可以按大小排序,字符串可以按字典顺序排序。Comparable接口通过其compareTo方法,允许对象自行决定如何与其他对象比较。
    • Serializable 接口:一个对象序列化的接口,一个类只有实现了Serializable接口,它的对象才能被序列化。简单理解就是,可以在网络传输。

image-20250122142849945

  1. String 类是 final 类,不能被其他的类继承。
  2. String 类有属性 private final char value[]; 用于存放字符串的内容,也就是说,字符串的内容实际上是存放在 value 数组中的。
  3. private final char value[]; :可以看到,value 数组是 final 修饰的。在java中,当final 修饰数组时,数组的引用不能被重新赋值,但数组的元素可以被修改。
public final char arr[] = {'1', '2', '3'};
char[] arr2 = {'1'};
//数组的引用不能重新赋值
//即arr不能再指向其他数组
//arr = arr2 这样就是错误的

//数组的元素可以被修改
arr[0] = '8';//这个是被允许的

2 String 对象创建的两种方式

  1. 直接将字符串赋值给 String 类型:String str1 = "xiong";
  2. 调用构造器:String str2 = new String("xiong");

两种方式的区别:

  • 方式一:先从常量池查看是否有 “xiong” 数据空间,如果有,直接指向常量池的对象;如果没有,则在常量池中创建 “xiong" 对象,然后指向,str1 最终指向的是常量池的空间地址。
  • 方式二:先在堆中创建空间,里面维护了 value 属性,指向常量池存储 ”xiong“ 的空间。如果常量池没有 “xiong” ,则会在常量池中进行创建,再让 value 指向;如果有,则 value 直接指向。
String str1 = "xiong";
String str2 = new String("xiong");

(1)创建 str1 时,首先检查常量池中是否已经存在 “xiong” ,如果不存在,就创建然后再让 str1 指向常量池中存储 “xiong” 的地址空间。如果存在,则直接指向。

(2)创建 str2 时,先在堆区创建一个 String 对象,该对象有属性 value 数组,value 数组首先检查常量池中是否已经存在 “xiong” ,如果不存在,就创建然后再让 value 指向常量池中存储 “xiong” 的地址空间。如果存在,则直接指向。

image-20250122152006774


3 测试题加深理解

(1) 例题一

String a = "xiong" + "da";
//创建了几个对象

解答: 创建了一个对象,在 使用 + 进行拼接时,编译器会进行一个优化,即上式等价于 String a = "xiongda"; 执行。

(2)例题二

String a = "xiong";
String b = "da";
String c = a + b;
//创建了几个对象

  我们使用 idea 进行debug 调试,看看 String c = a + b 是如何执行的:

首先,会进入 StringBuilder 类中的无参构造器中:

image-20250122153422921

构造器执行完之后,将进入 append 方法中,通过 super.append(str) 先将 “xiong” 添加进 StringBuilder 对象中,然后返回。

image-20250122153541904

“xiong” 完成添加之后,接着添加 “da”。

image-20250122153854807

然后调用 StringBuilder 的 toString() 方法,返回一个字符串 “xiongda”。

image-20250122153942706

(3) 例题三

  首先介绍一下 String 中的 intern() 方法:简单来说就是,如果有 String s = new String("xiong"); 如果执行 s.intern() ,那么如果常量池中已经存在 “xiong”,就会返回常量池存储 “xiong” 的空间地址,如果不存在,就会在常量池中创建,然后再返回。

image-20250122154215265

//下面的代码输出什么
String s1 = "xiong";
String s2 = "da";
String s3 = "xiongda";
String s4 = (s1 + s2).intern();
System.out.println(s3 == s4);//输出 true
System.out.println(s3.equals(s4));//输出true

4 String 类的常用方法

(1)equals()

  区分大小写,判断字符串的内容是否相等。

image-20250122173431292

使用:

String a = "xiong";
String b = new String("xiong");
System.out.println(a.equals(b));//true
//equals()方法比较的是字符串的内容是否相同

(2)equalsIgnoreCase()

  忽略大小写,判断字符串的内容是否相同。

image-20250122173719017

  字符串是区分大小写的,比如 abcAbc 这两个就是不同的字符串。但是,如果使用 equalsIgnoreCase() 方法进行比较这两个就是相等的。

String a = "abc";
String b = new String("Abc");
System.out.println(a.equalsIgnoreCase(b));//true
//equalsIgnoreCase()方法
//忽略大小写比较字符串的内容是否相同

(3)length()

  获取字符的个数,字符串的长度。

image-20250122174218012

String a = "123456";
System.out.println(a.length());//6
//字符串有6个字符,长度为6

(4)indexOf()

  • public int indexOf(int ch)

  获取字符在字符串中第一次出现的索引,索引从0开始,如果找不到,返回 -1。

image-20250122174616556

String a = "abcdefg";
int n = a.indexOf('c');
//n = 2,索引从0开始,c 的索引为2
  • public int indexOf(int ch, int formIndex)

    返回指定字符在此字符串中第一次出现的索引,从指定索引处(formIndex)开始搜索。

image-20250122175003612

String a = "123123";
//从索引为1的位置开始,获取字符在字符串中第一次出现的索引
int n = a.indexOf('1', 1);
// n = 3;从索引1开始查找,出现的第一个1的索引为3

(5)lastIndexOf()

image-20250122175330602

(6)substring()

  • public String substring(int beginIndex)

image-20250122175457482

  • public String substring(int beginIndex, int endIndex)

    截取范围为: [ b e g i n I n d e x , e n d I n d e x ) [beginIndex, endIndex) [beginIndex,endIndex)

image-20250122175517611

(7)trim()

  去除前后空格。

image-20250122175902235

String a = " abc ";
a = a.trim();// a="abc"
//去除了前后空格

(8)charAt()

  返回指定索引处的 char 值。

image-20250122180055157

String a = "abcd";
char ch = a.charAt(2);
// ch = c; 字符串索引为2的字符为c

(9)toUpperCase()

  将 String 中的所有字符转换为大写。

String a = "aBcdef";
a = a.toUpperCase();
// a = "ABCDEF";

(10)toLowerCase()

  将 String 中的所有字符转换为小写。

String a = "ABCdef";
a = a.toLowerCase();
// a = "abcdef";

(11)concat()

  将指定的字符串连接到此字符串的末尾。

image-20250122181016957

String a = "ab";
a = a.concat("c").concat("d");
// a = "abcd"

(12)replace()

image-20250122181228915

String a = "123123";
a = a.replace('2', '6');
// a = "163163"

(13)split()

  分割字符串,对于某些分割字符,我们需要转义,比如 |、\\ 等。

image-20250122181549740

String a = "My name is xiong";
String[] str = a.split(" ");
// str = {"My", "name", "is", "xiong"}

(14)compareTo()

  这个直接看源码:

public int compareTo(String anotherString) {
    // 获取当前字符串的长度
    int len1 = value.length;
    // 获取另一个字符串的长度
    int len2 = anotherString.value.length;
    // 计算两个字符串的最小长度,用于后续逐字符比较
    int lim = Math.min(len1, len2);
    // 将当前字符串的字符数组赋值给v1
    char v1[] = value;
    // 将另一个字符串的字符数组赋值给v2
    char v2[] = anotherString.value;

    // 初始化索引变量k,用于遍历字符数组
    int k = 0;
    // 遍历两个字符串的字符数组,直到最小长度lim
    while (k < lim) {
        // 获取当前索引位置的字符
        char c1 = v1[k];
        char c2 = v2[k];
        // 如果两个字符不相等
        if (c1 != c2) {
            // 返回两个字符的ASCII值差,表示字符串的字典序比较结果
            return c1 - c2;
        }
        // 如果字符相等,继续比较下一个字符
        k++;
    }
    // 如果所有字符都相等,返回两个字符串长度的差值
    // 如果长度相等,返回0,表示两个字符串相等
    // 如果当前字符串更长,返回正数,表示当前字符串大于另一个字符串
    // 如果当前字符串更短,返回负数,表示当前字符串小于另一个字符串
    return len1 - len2;
}
1. 逐字符比较:
  • 从两个字符串的起始位置开始,逐字符比较。
  • 如果在某个位置发现字符不相等,则直接返回这两个字符的ASCII值差(c1 - c2),表示字符串的字典序关系。
  • 如果字符相等,则继续比较下一个字符,直到遍历完较短字符串的长度(lim)。
2. 长度比较:
  • 如果所有字符都相等(即遍历完较短字符串后仍未分出胜负),则比较两个字符串的长度。
  • 如果当前字符串更长,返回正数;如果更短,返回负数;如果长度相等,返回0,表示两个字符串完全相等。
总结:

这段代码通过逐字符比较长度比较,实现了字符串的字典序比较,返回值表示两个字符串的大小关系:

  • 负数:当前字符串小于另一个字符串。
  • 正数:当前字符串大于另一个字符串。
  • 0:两个字符串相等。

(15)toCharArray()

image-20250122182308744

String a = "abcd";
char[] ch = a.toCharArray();
// ch = {'a', 'b', 'c', 'd'}

(16)format()

  格式化字符串:

  • %s :字符串
  • %c :字符
  • %d :整型
  • %.2f :浮点型,四舍五入保留2位小数。
//1. %s , %d , %.2f , %c 称为占位符
//2. 这些占位符由后面变量来替换
//3. %s 表示后面由字符串来替换
//4. %d 是整数来替换
//5. %.2f 表示使用小数来替换,替换后,只会保留小数点两位, 并且进行四舍五入的处理
//6. %c 使用char 类型来替换
String formatStr = "我的姓名是%s 年龄是%d,成绩是%.2f 性别是%c.希望大家喜欢我!";
String info2 = String.format(formatStr, "xiong", 18, 99.9, '男');
System.out.println("info2=" + info2);

二、StringBuffer 类

1 基本介绍

  1. java.lang.StringBuffer 代表可变的字符序列,可以对字符串内容进行增删。

  2. 很多方法与 String 相同,但 StringBuffer 是可变长度的。

  3. StringBuffer 是一个容器。

  4. StringBuffer 是 final 类,不能被继承。

  5. StringBuffer 继承了抽象类 AbstractStringBuilder。

image-20250122192704836

  1. AbstractStringBuilder 拥有 value 字符数组,StringBuffer 的字符串内容就存放在这个数组。

image-20250122192832229

  1. StringBuffer 的构造器。

image-20250122193944370

其中,字符串缓冲区就是 value 字符数组。

  • StringBuffer(String str)

    使用这个构造器时,value 的大小为 str.length() + 16


2 String 和 StringBuffer 相互转换

  在使用中,我们经常需要将 String 和 StringBuffer 进行转换,以下是转换的方式:

public class Test {
    public static void main(String[] args) {
        String str = "xiong";
        // Sting -> StringBuffer
        //1.使用构造器
        StringBuffer s1 = new StringBuffer(str);
        //2.使用 append()方法
        StringBuffer s2 = new StringBuffer();
        s2 = s2.append(str);
        
        // StringBuffer -> String
        StringBuffer s3 = new StringBuffer("da");
        //1.使用 StringBuffer 的toString()方法
        String str1 = s3.toString();
        //2.使用构造器
        String str2 = new String(s3);
    }
}

3 StringBuffer 类的常用方法

StringBuffer s = new StringBuffer("xiong");

(1)增: append()

s.append(",");
s.append("da");
// s = "xiong,da"

注意: 有很多重载的 append() 方法。具体查询可以通过 jdk 文档。

image-20250122200733790

(2)删: delete()

image-20250122200428611

StringBuffer str = new StringBuffer("xiong");
str.delete(1,3);// 删除索引为 1,2 的字符
// str = "xng"

(3)replace()

image-20250122201252064

(4)indexOf()

image-20250122201410897

image-20250122201429097

(5)insert()

  插入:

StringBuffer str = new StringBuffer("feimu");
//在索引为3的位置插入 "-"
str.insert(3,"-");
// str="fei-mu"

注意: StringBuffer 类中有很多重载的 append() 方法,有需要可以通过查阅官方文档。

image-20250122201807493

(6)length()

image-20250122201824578


三、StringBuilder 类

1 基本介绍

  1. 一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步(StringBuilder 不是线程安全的)。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候。如果可以,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。

  2. 在 StringBuilder 上的主要操作是 append() 方法和 insert() 方法,可重载这些方法,以接受任意类型的数据。

  3. StringBuffer 继承了抽象类 AbstractStringBuilder。

image-20250122220855669

  1. AbstractStringBuilder 拥有 value 字符数组,StringBuffer 的字符串内容就存放在这个数组。

2 StringBuilder 的方法和 StringBuffer 是一样的。

3 String、StringBuffer 和 StringBuilder 的比较

  1. StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且方法也一样。
  2. String :不可变字符序列,效率低,但是复用率高。
  3. StringBuffer :可变字符序列,效率较高(增删)、线程安全。
  4. StringBuilder :可变字符序列、效率最高、线程不安全。
  5. String 使用注意事项:
String s = "abc";
//实际上原来的"abc"对象会被丢弃
//又产生一个字符串对象 "abcd"
s = s + "d";
//如果多次执行这样的操作,会导致大量的副本字符串对象留存在内存中
//降低效率

四 、String、StringBuffer 和 StringBuilder 的选择

使用的原则:

  1. 如果字符串存在大量的修改操作,一般使用 StringBuffer 或 StringBuilder
  2. 如果字符串存在大量的修改操作,并且在单线程的情况,使用 StringBuilder
  3. 如果字符串存在大量的修改操作,并在多线程的情况,使用 StringBuffer
  4. 如果我们的字符串很少修改,被多个对象引用,使用 String,比如配置信息等。

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

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

相关文章

外设链接与中断

外设链接与中断 PC键盘处理过程 定制键盘的输入过程

考研408笔记之数据结构(五)——图

数据结构&#xff08;五&#xff09;——图 1. 图的基本概念 1.1 图的定义 1.2 有向图和无向图 在有向图中&#xff0c;使用圆括号表示一条边&#xff0c;圆括号里元素位置互换没有影响。 在无向图中&#xff0c;使用尖括号表示一条边&#xff0c;尖括号里元素位置互换则表示…

71,【3】buuctf web [HITCON 2017]SSRFme

进入靶场 左上角是IP地址&#xff0c;下面有一堆代码 <?php // 检查是否存在 HTTP_X_FORWARDED_FOR 头部信息 if (isset($_SERVER[HTTP_X_FORWARDED_FOR])) {// 如果存在&#xff0c;将其按逗号分隔&#xff0c;并将第一个元素作为新的 REMOTE_ADDR$http_x_headers explo…

【TypeScript】模块化和命名空间、类型查找、类型缩小

模块化和命名空间 ts 在模块化中遵循 esm 规范&#xff0c;而且推荐导入类型时前面加上 type 字段&#xff0c;这些可以让一个非TypeScript编译器比如Babel、swc或者esbuild知道什么样的导入可以被安全移除。 TypeScript有它自己的模块格式&#xff0c;名为namespaces&#x…

城市生命线安全保障:技术应用与策略创新

城市生命线工程是维系城市正常运行、满足群众生产生活需要的重要基础设施。随着城市化进程的加快&#xff0c;城市基础设施生命线安全运行的复杂性日益加剧&#xff0c;保障城市居民日常生活正常运行的水、电、气、热等各类地下管线以及桥梁、市政设施、轨道交通等城市基础设施…

MVCC在MySQL中实现无锁的原理

一&#xff1a;基础知识 我们知道MySQL是多线程并发处理任务的。MySQL使用了MVCC来实现事务并发的无锁机制。 而且我们还需要知道MySQL的四种隔离级别&#xff1a;读未提交&#xff0c;读已提交&#xff08;RC&#xff09;&#xff0c;可重复读&#xff08;RR&#xff09;&am…

WPF实战案例 | C# WPF实现大学选课系统

WPF实战案例 | C# WPF实现大学选课系统 一、设计来源1.1 主界面1.2 登录界面1.3 新增课程界面1.4 修改密码界面 二、效果和源码2.1 界面设计&#xff08;XAML&#xff09;2.2 代码逻辑&#xff08;C#&#xff09; 源码下载更多优质源码分享 作者&#xff1a;xcLeigh 文章地址&a…

HTML5 Canvas和JavaScript的3D粒子星系效果

HTML部分 基本结构包括<html>, <head>, 和 <body>标签。<title>标签设置了页面标题为“优化版3D粒子星系”。<style>块定义了一些基本样式&#xff1a; body&#xff1a;无边距&#xff0c;隐藏滚动条&#xff0c;黑色背景&#xff0c;禁用触摸…

再见 Crontab!Linux 定时任务的新选择!

引言 说到 Linux 下定时执行任务&#xff0c;大多数人可能会想到 crontab&#xff1f;没错&#xff0c;它的确是 Linux 下比较通用和方便的方式&#xff0c;但是今天我来介绍一种新的方法来创建定时任务并且支持更多更强大的功能。 Systemd 很多小伙伴应该听说过 Systemd&…

Unity入门1

安装之后无法获得许可证&#xff0c;可以考虑重装 新建项目 单击空白处生成脚本 双击c#文件 会自动打开vstudio 检查引用 如果没有引用&#xff0c;重开vstu&#xff0c;或者重新加载项目 hierarchy层级 scenes场景 assets资产 inspector督察 icon图标 资源链接&…

【二叉树】遍历总结!

在很多问题中&#xff0c;熟练掌握二叉树的遍历方法&#xff0c;能够轻松解决很多问题。 新建一棵二叉树root[1,null,2,3] 1、前序遍历 前序遍历的顺序为根节点->左子树->右子树&#xff0c;按照以上二叉树&#xff0c;遍历顺序为[1&#xff0c;2&#xff0c;3]。代码为…

(2)STM32 USB设备开发-USB虚拟串口

例程&#xff1a;STM32USBdevice: 基于STM32的USB设备例子程序 - Gitee.com 本篇为USB虚拟串口教程&#xff0c;没有知识&#xff0c;全是实操&#xff0c;按照步骤就能获得一个STM32的USB虚拟串口。本例子是在野火F103MINI开发板上验证的&#xff0c;如果代码中出现一些外设的…

ASP .NET Core 学习(.NET9)部署(一)windows

在windows部署 ASP .NET Core 的时候IIS是不二选择 一、IIS安装 不论是在window7 、w10还是Windows Server&#xff0c;都是十分简单的&#xff0c;下面以Windows10为例 打开控制面版—程序—启用或关闭Windows功能 勾选图中的两项&#xff0c;其中的子项看需求自行勾选&am…

Java并发编程面试题:线程池Fork/Join(19题)

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

fyne 选项卡设计

用户界面的设计至关重要&#xff0c;它直接影响着用户体验。选卡设计作为一种常见的界面布局方式&#xff0c;能够有效地组织和展示信息&#xff0c;使用户能够方便快捷地浏览和操作。 Fyne 是一个用 Go 语言编写的跨平台 GUI 框架&#xff0c;它提供了丰富的组件和功能&#…

MySQL——主从同步

提醒&#xff1a;进行配置时&#xff0c;需要确保一主两从的操作系统、MySQL版本一致&#xff0c;否则将出现问题 环境介绍 服务器IP主服务器172.25.254.10从服务器-1172.25.254.11从服务器-2172.25.254.12 配置 # 快速配置&#xff0c;选择多重执行&#xff0c;确保版本一…

IDEA中Maven使用的踩坑与最佳实践

文章目录 IDEA中Maven使用的踩坑与最佳实践一、环境配置类问题1. Maven环境配置2. IDEA中Maven配置建议 二、常见问题与解决方案1. 依赖下载失败2. 依赖冲突解决3. 编译问题修复 三、效率提升技巧1. IDEA Maven Helper插件使用2. 常用Maven命令配置3. 多模块项目配置4. 资源文件…

VIVADO-block desgn 中时钟连线报错

问题描述 1.自定义的IP核由于封装不规范&#xff0c;输出的时钟引脚缺少该时钟的相关信息 正常时钟引脚属性 异常的时钟引脚属性 2.run connection automation 中无法找到这种缺少信息的时钟源 3.axi_clk与axi interconnect时钟频率不匹配 解决方案&#xff1a; 1.用BUFG将缺少…

CSDN 博客之星 2024:默语的技术进阶与社区耕耘之旅

CSDN 博客之星 2024&#xff1a;默语的技术进阶与社区耕耘之旅 &#x1f31f; 默语&#xff0c;是一位在技术分享与社区建设中坚持深耕的博客作者。今年&#xff0c;我有幸再次入围成为 CSDN 博客之星TOP300 的一员&#xff0c;这既是对过往努力的肯定&#xff0c;也是对未来探…

BUUCTF_Web(UPLOAD COURSE 1)

打开靶机&#xff0c;发现需要上传文件&#xff0c;尝试一句话木马蚁剑链接 一句话木马 【基本原理】利用文件上传漏洞&#xff0c;往目标网站中上传一句话木马&#xff0c;然后你就可以在本地通过中国菜刀chopper.exe即可获取和控制整个网站目录。表示后面即使执行错误&#…