Java String 类笔记

在 Java 中,String 是最常用也是最重要的类之一。无论是处理文本、构建日志,还是作为参数传递,String 都无处不在。本文将深入浅出地介绍 String 的常用方法,辨析 String、StringBuffer、StringBuilder 三者的区别,并解释 String 为何设计为不可变。

一、String 的常用方法

String 类提供了丰富的方法来操作字符串。下面列举了最常用的一些方法,并附有简单示例。

1. 获取长度

  • int length():返回字符串的长度(字符个数)。

    java 复制代码
    String str = "Hello";
    System.out.println(str.length()); // 5

2. 判断内容是否相等

  • boolean equals(Object obj):比较两个字符串的内容是否完全相同(区分大小写)。

  • boolean equalsIgnoreCase(String another):忽略大小写比较内容。

    java 复制代码
    String s1 = "Java";
    String s2 = "java";
    System.out.println(s1.equals(s2));          // false
    System.out.println(s1.equalsIgnoreCase(s2)); // true

3. 截取子串

  • String substring(int beginIndex):从指定索引开始截取到末尾。

  • String substring(int beginIndex, int endIndex):截取 [beginIndex, endIndex) 范围内的子串。

    java 复制代码
    String str = "Hello World";
    System.out.println(str.substring(6));    // World
    System.out.println(str.substring(0, 5)); // Hello

4. 去除首尾空格

  • String trim():去除字符串首尾的空白字符(空格、制表符等)。

    java 复制代码
    String str = "  Hello  ";
    System.out.println(str.trim()); // "Hello"

5. 替换字符或子串

  • String replace(char oldChar, char newChar):替换所有指定字符。

  • String replace(CharSequence target, CharSequence replacement):替换所有指定子串。

    java 复制代码
    String str = "hello world";
    System.out.println(str.replace('l', 'L'));      // heLLo worLd
    System.out.println(str.replace("world", "Java")); // hello Java

6. 判断是否为空字符串

  • boolean isEmpty():判断字符串长度是否为 0。注意:如果字符串为 null,调用此方法会抛出 NullPointerException,因此需要先判空。

    java 复制代码
    String s1 = "";
    String s2 = null;
    System.out.println(s1.isEmpty()); // true
    // System.out.println(s2.isEmpty()); // 报错!

7. 其他常用方法

  • char charAt(int index):返回指定索引处的字符。

  • int indexOf(String str):返回指定子串第一次出现的索引。

  • String[] split(String regex):根据正则表达式分割字符串。

  • String toLowerCase() / toUpperCase():转换为小写/大写。

  • boolean startsWith(String prefix) / endsWith(String suffix):判断是否以指定前缀/后缀开头/结尾。

二、String、StringBuffer、StringBuilder 的区别与联系

在 Java 中,处理字符串有三种主要的类:String、StringBuffer 和 StringBuilder。它们的主要区别在于 可变性 、线程安全性 和 性能。

特性 String StringBuffer StringBuilder
可变性 不可变(Immutable) 可变(Mutable) 可变(Mutable)
线程安全 安全(不可变天然安全) 安全(方法使用 synchronized) 不安全
性能 低(频繁修改产生大量对象) 中等(有同步开销) 最高(无同步)
适用场景 字符串内容不变或很少变化 多线程环境下频繁修改 单线程环境下频繁修改

1. 为什么要有三个类?

  • String 适用于内容固定的场景,例如常量、少量拼接。由于其不可变性,它天然支持常量池,且作为 Map 的键非常安全。

  • StringBuilder 是 JDK 1.5 引入的,用于替代 StringBuffer 的单线程版本,性能更高。

  • StringBuffer 是早期版本就存在的,线程安全但性能较低,现在主要用于多线程环境。

2. 示例对比

java 复制代码
// String 拼接:每次都会生成新对象
String s = "a";
s += "b"; // 实际上创建了新的 String 对象

// StringBuilder 拼接:在原有对象上修改
StringBuilder sb = new StringBuilder("a");
sb.append("b"); // 修改同一个对象

三、String 为什么是不可变的?

String 被设计为不可变类,即一旦创建,其内容就不能被改变。这是出于多方面考虑的精心设计。

1. 源码层面

String 类的源码中,存储字符的数组被声明为 private final char value[]:

  • final 保证了 value 引用不可变(即不能指向另一个数组)。

  • private 且没有提供修改数组内容的方法,确保了外部无法修改数组元素。

2. 设计原因

  • 线程安全:不可变对象天生线程安全,可以在多线程环境中自由共享,无需同步。

  • 字符串常量池:JVM 维护了一个字符串常量池,当使用字面量创建字符串时,如果池中已存在相同内容的字符串,则直接返回池中的引用,从而节省内存。如果 String 可变,那么修改一个引用会影响所有引用该字符串的对象,导致混乱。

  • 哈希缓存 :String 的哈希码在创建时计算并缓存(通过 hash 字段),因为不可变,所以哈希值不会改变,这提高了作为 HashMap 键的效率。

  • 安全性:String 常被用作参数(如网络连接、文件路径等),如果可变,可能会被篡改,带来安全风险。

3. 不可变的优点总结

  • 线程安全

  • 支持字符串常量池,节约内存

  • 哈希值可缓存,提高效率

  • 防止参数被篡改,增强安全性

4. 不可变的缺点

  • 频繁修改字符串时会产生大量临时对象,增加 GC 负担。此时应使用 StringBuilder 或 StringBuffer。

四、总结

  • String 是不可变、线程安全的,适用于内容不变的场景。

  • StringBuilder 是可变、非线程安全的,适用于单线程下频繁修改。

  • StringBuffer 是可变、线程安全的,适用于多线程下频繁修改。

  • String 的不可变性带来了安全、高效、节省内存等诸多好处,是 Java 设计中的经典范例。

相关推荐
非优秀程序员7 小时前
第04章 邮箱大战,163 与 QQ 的暗战|《互联网产品恩仇录》
java·vue.js·架构
知已难寻8 小时前
Docker 入门:容器技术与 Docker 基础
java·运维·服务器·docker·云原生·容器
文丑颜不良啊10 小时前
LeetCode2481~2500题目解析
java·leetcode
Flynn Liang11 小时前
同一需求三套写法:用 Spring AI、LangChain4j、AgentScope Java 各实现一个带工具调用的 RAG 助手(实战对比)
java·人工智能·大模型·架构设计·spring ai·langchain4j·agentscope
聪明的笨猪猪11 小时前
实际工程问题:AI 生成 Spring Cache(@Cacheable / @CachePut / @CacheEvict)缓存注解踩坑
java·经验分享·面试·ai编程
愿有所息11 小时前
记一次 ARM64 + JDK8 上 fastjson2 的诡异数据错乱
java
秋饼12 小时前
MCP 2026-07-28 无状态协议大改版:Spring AI 2.1 多轮往返请求与网关路由落地
java·ai·技术分享·后端开发
SL_staff13 小时前
JVS-BI 实战:业务人员如何用零代码 ELT + 可视化配置构建实时经营分析闭环
java·spring·全栈
SL_staff13 小时前
企业AI落地难?JVS-AI渐进式实践:安全可控、小切口验证、标准化沉淀与规模化复制
java·开源·aigc
SL_staff15 小时前
JVS数字底座实践:构建企业级统一内容管理平台的技术路径
java·产品