String、StringBuffer和StringBuilder,别再用错了!

写 Java 的时,你有没有遇到过这种情况:拼接个字符串,发现程序变慢了?或者多线程环境下,拼出来的字符串乱了?其实,很多时候问题就出在于你用了不该用的"字符串"。

Java里有三个常用的字符串相关类:StringStringBufferStringBuilder。它们看着像一家人,但如果用错了地方,可能会出现性能差或者其它的问题。

一、String:用在"不变"的场景

String是不可变的。一旦你创建了一个字符串,它就定下来了,改不了。如果你改了它,其实是新建了一个字符串。

比如:

java 复制代码
String str = "Hello";
str = str + " World";

你以为是改了str?其实是在内存里新建了一个"Hello World",原来的"Hello"被丢掉了。

使用场景:

  • 字符串内容固定不变
  • 作为配置项、常量、Map的key
  • 简单拼接,次数少(1~2 次)

案例:

你从配置文件读了个数据库地址:

java 复制代码
String dbUrl = "jdbc:mysql://localhost:3306/mydb";

这个地址不会变,就用String,简单直接。

注意:

别拿 String去搞循环拼接!比如:

java 复制代码
String result = "";
for (int i = 0; i < 1000; i++) {
    result += i; // 每次都新建对象,内存爆炸!
}

这种写法在小数据量时看不出问题,数据一大,程序直接卡死。

二、StringBuilder:单线程下,拼接字符串的"快枪手"

如果你要在一个线程里 拼接大量字符串StringBuilder是首选。

它可变,而且速度快,内存消耗小。

使用场景:

  • 单线程下大量字符串拼接
  • 构造 JSON、SQL 语句
  • 日志信息组装

案例 1:拼接 SQL

java 复制代码
StringBuilder sql = new StringBuilder("SELECT * FROM users WHERE 1=1");
if (age > 0) {
    sql.append(" AND age > ").append(age);
}
if (name != null) {
    sql.append(" AND name LIKE '%").append(name).append("%'");
}

这种动态 SQL,用StringBuilder拼,又快又安全。

案例 2:生成日志消息

java 复制代码
StringBuilder logMsg = new StringBuilder();
logMsg.append("用户 ").append(userId)
      .append(" 在 ").append(new Date())
      .append(" 执行了操作:").append(action);
System.out.println(logMsg.toString());

拼接几个字段,清晰又高效。 只要是一个人干活(单线程),拼字符串多,就用StringBuilder

三、StringBuffer:多线程下的"安全卫士"

StringBufferStringBuilder功能几乎一样,都能拼接字符串。区别在哪?线程安全。

StringBuffer的每个方法都加了锁(synchronized),多个线程同时操作也不会乱。

使用场景:

  • 多线程环境下拼接字符串
  • 全局共享的字符串缓冲区
  • 对线程安全有要求的场景

案例:

假设你有个计数器,多个线程往一个日志缓冲区里写信息:

java 复制代码
// 全局共享
StringBuffer sharedLog = new StringBuffer();

// 线程1
new Thread(() -> {
    sharedLog.append("Thread-1: 开始处理\n");
    // ...处理逻辑
    sharedLog.append("Thread-1: 处理完成\n");
}).start();

// 线程2
new Thread(() -> {
    sharedLog.append("Thread-2: 开始处理\n");
    // ...处理逻辑
    sharedLog.append("Thread-2: 处理完成\n");
}).start();

这时候用StringBuilder就可能出问题------两个线程同时写,内容可能错乱、丢失。而StringBuffer能保证顺序正确。

但是!

加锁是有代价的。StringBufferStringBuilder慢一点。所以,如果不是多线程,别用它

四、总结

场景 用哪个? 为什么?
字符串不变,简单使用 String 简单直观,适合常量
单线程,大量拼接 StringBuilder 快,不加锁,效率高
多线程,共享拼接 StringBuffer 安全,防止数据错乱
循环拼接(不管多少线程) 别用 String 性能极差,容易 OOM
  • 不变用 String
  • 单线程拼接用 StringBuilder
  • 多线程拼接用 StringBuffer

所以,别小看这几个类的选择。用对了,程序真的可以很稳;

相关推荐
RainbowSea13 分钟前
1. LangChain4J 理论概述
java·langchain·llm
IT_陈寒20 分钟前
Java性能优化实战:5个立竿见影的技巧让你的应用提速50%
前端·人工智能·后端
刘 大 望35 分钟前
网络编程--TCP/UDP Socket套接字
java·运维·服务器·网络·数据结构·java-ee·intellij-idea
没有bug.的程序员1 小时前
AOT 编译与 GraalVM 实战:Java 云原生的终极进化
java·python·云原生·graalvm·aot
找不到、了1 小时前
常用的分布式ID设计方案
java·分布式
野区捕龙为宠1 小时前
Unity Netcode for GameObjects(多人联机小Demo)
java·unity·游戏引擎
陈随易1 小时前
10年老前端,分享20+严选技术栈
前端·后端·程序员
汪子熙2 小时前
计算机世界里的 blob:从数据库 BLOB 到 Git、Web API 与云存储的二进制宇宙
后端
十八旬2 小时前
苍穹外卖项目实战(日记十)-记录实战教程及问题的解决方法-(day3-2)新增菜品功能完整版
java·开发语言·spring boot·mysql·idea·苍穹外卖
鞋尖的灰尘2 小时前
springboot-事务
java·后端