Java中字符串比较应使用equals()而非==,因==比较内存地址而equals比较内容;substring索引需防越界;replace不支持正则而replaceAll支持;循环拼接用StringBuilder更高效;字符串不可变导致每次操作都生成新对象。

String.equals() 为什么不能用 == 比较字符串内容
Java 中 == 比较的是两个引用是否指向同一块内存地址,而 equals() 才真正比较字符序列是否一致。很多初学者在判断字符串值相等时误用 ==,导致逻辑出错,尤其在从用户输入、配置文件或网络读取字符串后。
- 字符串字面量(如
"hello")在常量池中复用,"a" == "a"返回true;但new String("a") == "a"是false - 推荐统一使用
str1.equals(str2),避免空指针——更安全的写法是"abc".equals(str)(把字面量放前面) - 忽略大小写用
equalsIgnoreCase(),比如验证 HTTP 方法时:method.equalsIgnoreCase("post")
substring() 的索引边界容易越界
substring(int beginIndex, int endIndex) 的 endIndex 是**不包含**的,且两个参数都必须满足 0 ≤ beginIndex ≤ endIndex ≤ length(),否则抛 StringIndexOutOfBoundsException。
- 常见错误:想取最后 3 个字符写成
s.substring(s.length() - 3, s.length()),但当s.length() 时直接崩溃 - 稳妥做法是先判断长度:
if (s.length() >= 3) { tail = s.substring(s.length() - 3); } -
substring(beginIndex)等价于substring(beginIndex, length()),可省略第二个参数
replace() 和 replaceAll() 的根本区别在正则支持
replace(CharSequence target, CharSequence replacement) 做**字面量替换**,不解析正则;而 replaceAll(String regex, String replacement) 第一个参数是正则表达式,功能强但易出错。
- 想把所有
"."替换成"-",用replace(".", "-")即可;若误用replaceAll(".", "-"),会把每个字符都替换成"-"(因为.在正则中是通配符) - 真要正则替换,需转义:
replaceAll("\\.", "-");或者用Pattern.quote(".")包装 - 性能上,
replace()更快,无正则引擎开销,日常简单替换优先选它
字符串拼接用 StringBuilder 还是 + 号
在循环内反复拼接字符串时,用 + 会隐式创建多个 StringBuilder 实例,造成对象频繁分配和 GC 压力;而显式用 StringBuilder 可复用缓冲区,适合大量拼接场景。
立即学习“Java免费学习笔记(深入)”;
- 方法内单次拼接(如
"Name: " + name + ", Age: " + age)会被编译器自动优化为StringBuilder,无需手动改 - 循环中拼接必须用
StringBuilder:StringBuilder sb = new StringBuilder(); for (String s : list) { sb.append(s).append(","); } String result = sb.toString(); - 注意
StringBuilder非线程安全;多线程环境下考虑StringBuffer(但多数情况不需要)
字符串不可变性是贯穿所有操作的基础约束——每次“修改”实际都生成新对象,原字符串不变。这个特性决定了缓存、安全性和性能表现,也解释了为什么像 trim()、toUpperCase() 都返回新实例而不是就地修改。









