news 2026/10/9 10:25:49

Java 常用 API(一):String 与 StringBuilder

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 常用 API(一):String 与 StringBuilder

前言

从这篇开始进入Java 常用 API。这一篇关于两个最高频的类:String和StringBuilder。

String 是 Java 里用得最多的类,没有之一。期待和你的一起进步

一、String 的不可变性

1.1 什么是不可变性?

String 对象一旦创建,它的内容就不能被修改。

java

String s = "hello"; s = "world"; // 这不是修改,是重新指向了一个新对象

看起来s变了,但实际上:

  • 原来的"hello"对象还在,没变

  • 新的"world"对象被创建

  • s重新指向了"world"

1.2 为什么不可变?

看 String 的源码:

java

public final class String { private final char[] value; // JDK 8 // private final byte[] value; // JDK 9+ }

两个关键点:

  1. class 用 final 修饰:不能被继承,防止子类破坏不可变性

  2. value 数组用 final 修饰:引用不能变,且 String 内部不提供修改数组的方法

1.3 代码验证

java

String s1 = "hello"; String s2 = s1; s1 = s1 + " world"; System.out.println(s1); // hello world System.out.println(s2); // hello

s1拼接后指向了新对象,s2还是指向原来的"hello",不受影响。

1.4 我的理解

String 就像刻在石头上的字。你想改,改不了,只能重新刻一块新的石头,然后把牌子指过去。

核心一句话:String 内容不可变,任何"修改"都是创建新对象。


二、字符串常量池

2.1 什么是字符串常量池?

字符串常量池(String Pool)是 JVM 在堆内存中开辟的一块区域,专门用来存放字符串字面量。

2.2 两种创建方式的区别

java

String s1 = "hello"; // 直接赋值,走常量池 String s2 = new String("hello"); // new 创建,走堆内存

内存结构:

text

栈内存 常量池(堆中) 堆内存 +------+ +------------+ +----------------+ | s1 | --> | "hello" | <----| new String 对象 | +------+ +------------+ +----------------+ | s2 | ----------------------->| value -> "hello"| +------+ +----------------+

2.3 代码验证

java

String s1 = "hello"; String s2 = "hello"; String s3 = new String("hello"); System.out.println(s1 == s2); // true,都指向常量池同一个对象 System.out.println(s1 == s3); // false,s3 是堆里的新对象

2.4 常量池的好处

  1. 节省内存:相同字面量只存一份

  2. 提高效率:直接复用,不用重新创建

2.5 我的理解

常量池就像公共图书馆。你说"我要《如何让富婆爱上我》这本书",管理员先看看书架上有没有,有就直接给你(复用),没有才去买一本放上去。

new String("hello")就像你自己复印了一本,虽然内容一样,但和图书馆那本不是同一本。

核心一句话:字面量走常量池,new 走堆内存。


三、String 的 equals 与 == 的区别

3.1 区别

对比项==equals
比较内容地址(是不是同一个对象)内容(字符是否相同)
所属运算符Object 类的方法
String 中比较地址重写后比较内容

3.2 代码示例

java

String s1 = "hello"; String s2 = "hello"; String s3 = new String("hello"); System.out.println(s1 == s2); // true,同一对象 System.out.println(s1 == s3); // false,不同对象 System.out.println(s1.equals(s3)); // true,内容相同

3.3 equals 源码

java

public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String) anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }

先比地址,地址相同直接返回 true;地址不同再逐个字符比较。

3.4 我的理解

==就是"是不是同一本书",equals就是"内容是不是一样"。

你和同学各拿一本《Java 入门》,==问的是"你俩拿的是不是同一本",equals问的是"你俩书的内容是不是一样"。

核心一句话:== 比地址,equals 比内容,字符串比较一律用 equals。


四、String 的构造方法

4.1 常用构造方法

构造方法说明
String()空字符串
String(String original)复制一个字符串
String(char[] value)用字符数组创建
String(char[] value, int offset, int count)用字符数组的一部分创建
String(byte[] bytes)用字节数组创建(默认平台编码)
String(byte[] bytes, Charset charset)用字节数组 + 指定编码创建

4.2 代码示例

java

// 空字符串 String s1 = new String(); System.out.println(s1); // "" // 复制 String s2 = new String("hello"); System.out.println(s2); // hello // 字符数组 char[] chars = {'h', 'e', 'l', 'l', 'o'}; String s3 = new String(chars); System.out.println(s3); // hello // 字符数组的一部分 String s4 = new String(chars, 1, 3); System.out.println(s4); // ell // 字节数组 byte[] bytes = {104, 101, 108, 108, 111}; String s5 = new String(bytes); System.out.println(s5); // hello

4.3 我的理解

构造方法就是给你多种方式去造一个 String。可以用字符数组造,可以用字节数组造,也可以复制一个现成的。

核心一句话:String 构造方法支持空串、复制、字符数组、字节数组等多种创建方式。


五、String 常用 API

5.1 判断类

方法说明
equals(Object obj)比较内容
equalsIgnoreCase(String str)忽略大小写比较
contains(String str)是否包含子串
startsWith(String prefix)是否以某前缀开头
endsWith(String suffix)是否以某后缀结尾
isEmpty()是否为空字符串

5.2 获取类

方法说明
length()长度
charAt(int index)获取指定位置字符
indexOf(String str)第一次出现的索引
lastIndexOf(String str)最后一次出现的索引
substring(int begin)从 begin 截到末尾
substring(int begin, int end)截取 [begin, end)

5.3 转换类

方法说明
toCharArray()转字符数组
getBytes()转字节数组
toLowerCase()转小写
toUpperCase()转大写
trim()去掉首尾空白
replace(CharSequence, CharSequence)替换

5.4 分割与拼接

方法说明
split(String regex)按正则分割
join(CharSequence, CharSequence...)静态方法,拼接

5.5 代码示例

java

String s = " Hello, World "; System.out.println(s.length()); // 16 System.out.println(s.trim()); // "Hello, World" System.out.println(s.trim().toLowerCase()); // "hello, world" System.out.println(s.contains("World")); // true System.out.println(s.trim().charAt(0)); // 'H' System.out.println(s.trim().substring(0, 5));// "Hello" System.out.println(s.trim().indexOf("o")); // 4 String[] parts = "a,b,c".split(","); System.out.println(Arrays.toString(parts)); // [a, b, c] String joined = String.join("-", "a", "b", "c"); System.out.println(joined); // a-b-c

5.6 我的理解

String 的 API 分四类:判断、获取、转换、分割拼接。不用全背,记住常用的就行,其余的用的时候查文档。

核心一句话:String API 分判断、获取、转换、分割拼接四类。


六、StringBuilder 的作用和意义

6.1 为什么需要 StringBuilder?

String 是不可变的,每次拼接都会创建新对象:

java

String s = ""; for (int i = 0; i < 1000; i++) { s += i; // 每次循环都创建新 String 对象 }

上面这段代码,循环 1000 次,创建了 1000 个 String 对象,效率极低。

用 StringBuilder:

java

StringBuilder sb = new StringBuilder(); for (int i = 0; i < 1000; i++) { sb.append(i); // 始终操作同一个对象 } String s = sb.toString();

6.2 StringBuilder 的特点

  1. 可变:内部维护一个 char 数组,可以动态扩容

  2. 高效:拼接时不会创建新对象

  3. 非线程安全:多线程环境下可能出问题

6.3 我的理解

String 像刻石头,改一次就得重新刻一块。StringBuilder 像白板,可以反复擦写,效率高得多。

核心一句话:StringBuilder 可变,适合频繁拼接;String 不可变,适合少量固定字符串。


七、StringBuilder 常用方法

7.1 常用 API

方法说明
append(...)追加内容,返回自身
insert(int, ...)在指定位置插入
delete(int start, int end)删除 [start, end)
deleteCharAt(int index)删除指定位置字符
replace(int start, int end, String str)替换
reverse()反转
toString()转成 String
length()长度
charAt(int index)获取指定位置字符

7.2 代码示例

java

StringBuilder sb = new StringBuilder("hello"); sb.append(" world"); // hello world sb.insert(0, "say: "); // say: hello world sb.delete(0, 5); // hello world sb.replace(0, 5, "HELLO"); // HELLO world sb.reverse(); // dlrow OLLEH System.out.println(sb.toString());

7.3 链式调用

append、insert、delete等方法都返回this,所以可以链式调用:

java

String result = new StringBuilder() .append("Hello") .append(", ") .append("World") .append("!") .toString(); System.out.println(result); // Hello, World!

7.4 我的理解

StringBuilder 的方法大多返回自身,所以能像流水线一样一直点下去,写起来很顺。

核心一句话:StringBuilder 方法返回自身,支持链式调用。


八、StringBuilder vs StringBuffer

8.1 区别

对比项StringBuilderStringBuffer
线程安全❌ 不安全✅ 安全
效率高低
版本JDK 1.5JDK 1.0
适用场景单线程多线程

8.2 为什么 StringBuffer 线程安全?

StringBuffer 的方法大多用synchronized修饰:

java

public synchronized StringBuffer append(String str) { // ... }

加锁保证同一时刻只有一个线程能操作,所以安全,但效率降低。

8.3 如何选择?

  • 单线程:用 StringBuilder(绝大多数情况)

  • 多线程:用 StringBuffer

8.4 我的理解

StringBuilder 像一个人用白板,随便写,快。StringBuffer 像多人共用白板,得排队,一次只能一个人写,安全但慢。

实际开发中,绝大多数场景是单线程,所以StringBuilder 用得更多。

核心一句话:单线程用 StringBuilder,多线程用 StringBuffer。


九、核心口诀

知识点口诀
String 不可变内容不可改,改就创建新对象
字符串常量池字面量走常量池,new 走堆
equals vs ==== 比地址,equals 比内容
String 构造空串、复制、字符数组、字节数组
String API判断、获取、转换、分割拼接
StringBuilder可变,适合频繁拼接
StringBuilder APIappend/insert/delete/reverse,支持链式
StringBuilder vs StringBuffer单线程 StringBuilder,多线程 StringBuffer

十、常见易错点

易错点说明
用 == 比较字符串内容必须用 equals,== 比的是地址
循环里用 String 拼接每次创建新对象,效率极低,改用 StringBuilder
混淆常量池和堆字面量在常量池,new 在堆
StringBuilder 当线程安全用StringBuilder 非线程安全,多线程用 StringBuffer
忘记 toString()StringBuilder 转 String 必须调 toString()
substring 越界end 不能超过 length,且 begin ≤ end
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 10:25:10

手把手教你学Simulink——毫米波雷达与激光雷达的数据融合通信

目录 手把手教你学Simulink——毫米波雷达与激光雷达的数据融合通信 一、系统目标与融合层级 1.1 传感器分工(教学初值) 1.2 三种融合架构 二、场景与坐标基准 2.1 坐标链 2.2 时间同步 三、毫米波雷达建模 3.1 理想/概率目标模型(快、做融合首选) 3.2 FMCW物理层…

作者头像 李华
网站建设 2026/10/9 10:20:54

圆柱电池自动线技术解析:自动物流、化成分容与智能制造系统集成

随着动力电池和储能电池行业快速发展&#xff0c;圆柱电池制造正从传统人工模式向智能制造模式升级。自动化生产线已经成为提高效率、降低成本以及提升产品一致性的重要手段。本文从工程技术角度分析圆柱自动线的组成架构及关键技术。一、什么是圆柱自动线圆柱自动线是指将生产…

作者头像 李华
网站建设 2026/10/9 10:20:40

【Web全栈进阶】FastAPI工程化:APIRouter拆分 + 配置 + 依赖注入

之前的FastAPI还活在单文件里&#xff1a;所有路由挤在一个main.py。 200行时没问题&#xff0c;500行时没人敢动——今天把它升级成“分模块的工程”&#xff0c;用早报站的API实战三件套&#xff1a;APIRouter拆路由、Settings管配置、Depends依赖注入。 &#x1f3af; 本篇产…

作者头像 李华
网站建设 2026/10/9 10:17:49

OpenClaw与Claude Code实战对比:TaoToken统一Key接入下的选型指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华