Java String不可变,所有操作均返回新字符串;比较用equals()而非==;substring()索引从0开始且右边界不包含;replace()字面量替换,replaceAll()正则替换;trim()仅处理ASCII空格,strip()(JDK11+)支持Unicode空白。

Java 的 String 类不可变,所有“修改”操作实际都返回新字符串——这是理解其方法行为的关键前提。别指望调用 trim() 或 replace() 后原字符串变了,它不会。
判断与比较:equals()、equalsIgnoreCase()、compareTo() 不能用 ==
用 == 比较字符串内容是常见错误,它比的是引用地址,不是字符序列。哪怕两个字面量相同(如 "abc" == "abc")可能为 true(因字符串常量池优化),但一旦涉及运行时拼接(如 new String("abc") == "abc")就必为 false。
正确做法:
- 内容相等用
equals();忽略大小写用equalsIgnoreCase() - 需要顺序排序或判大小时用
compareTo()(返回负数/0/正数) -
Objects.equals(str1, str2)可安全处理任一参数为null的情况
提取子串:substring() 的索引边界和越界行为
substring(int beginIndex) 和 substring(int beginIndex, int endIndex) 都基于 0 起始索引,且 endIndex 是**不包含**的右边界。
立即学习“Java免费学习笔记(深入)”;
容易出错的点:
-
beginIndex必须 ≥ 0,endIndex必须 ≤ 字符串长度,否则抛StringIndexOutOfBoundsException -
substring(0, str.length())等价于原字符串;substring(str.length())返回空字符串"" - 空字符串调用
substring(0)合法,但substring(1)就越界
String s = "hello"; System.out.println(s.substring(0, 2)); // "he" System.out.println(s.substring(3)); // "lo" System.out.println(s.substring(5)); // ""
查找与替换:indexOf()、lastIndexOf()、replace()、replaceAll() 的语义差异
indexOf() 和 lastIndexOf() 返回首次/末次匹配的下标(没找到返回 -1),只支持字符或子串,不支持正则。
替换操作要注意:
-
replace(char oldChar, char newChar)和replace(CharSequence target, CharSequence replacement)替换**所有匹配项**,且不走正则引擎 -
replaceAll(String regex, String replacement)第一个参数是正则表达式,比如想把点号.替换成\\.才能匹配字面量点 -
replaceFirst()仅替换第一个匹配(也按正则解析)
String s = "a.b.c";
System.out.println(s.replace(".", "-")); // "a-b-c" (字面量替换)
System.out.println(s.replaceAll("\\.", "-")); // "a-b-c" (正则需转义)
System.out.println(s.replaceAll(".", "-")); // "---" (正则中 . 匹配任意字符)
转换与校验:trim()、isBlank()、lines()、strip() 的 JDK 版本适配
trim() 只删 ASCII 空格(U+0000–U+0020),对全角空格、零宽空格、换行符无效。JDK 11 引入的 strip() 才真正按 Unicode 标准清理空白字符。
其他关键点:
-
isBlank()(JDK 11+)比isEmpty()更严格:空字符串、纯空白(含制表符、换行符等)都返回true -
lines()(JDK 11+)按行分割,自动处理\n、\r\n、\r,返回Stream,比split("\\R")更可靠 - JDK 8 项目若需类似
strip()行为,可用replaceAll("^\\s+|\\s+$", "")(注意正则中的\\s在 JDK 8 已支持 Unicode 空白)
最易被忽略的是:所有这些方法都不改变原 String 对象。每次调用都是新建对象,频繁链式调用(如 s.trim().toLowerCase().replace(...))会产生多个中间字符串——在性能敏感路径里,该用 StringBuilder 就别硬撑 String。










