string不可变是因final类、private final字符数组(jdk8为char[],jdk9+为byte[])及所有操作返回新对象三重保障;实现常量池复用、线程安全、hashmap键稳定与敏感信息防护。

String 为什么不可变
Java 中的 String 类被 final 修饰,内部存储字符的数组(JDK8 是 private final char[] value,JDK9+ 改为 byte[])也用 final 修饰。这意味着:对象一旦创建,其内容地址和底层数据引用都无法被更改。
所谓“修改字符串”,比如 s = s + "abc" 或 s.replace("a", "x"),实际是创建一个新 String 对象,原对象保持不变,只是变量 s 指向了新地址。原来的字符串若无引用,就会等待垃圾回收。
- 字面量方式(
"hello")会进入字符串常量池,相同内容只存一份 -
new String("hello")总是在堆中新建对象,即使内容重复 - 不可变性带来线程安全、哈希值可缓存(
hashCode()只算一次)、适合做 Map 键等优势
四种字符串比较方法怎么选
判断两个字符串是否“一样”,不能只靠 ==,得看你想比什么:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
==:只比较内存地址是否相同,适用于确认是不是同一个对象(如常量池复用:"abc" == "abc"返回true) -
.equals():最常用,逐字符比较内容是否相等,区分大小写("Abc".equals("abc")→false) -
.compareTo():按字典序比较,返回负数/零/正数,适合排序或判断大小关系("apple".compareTo("banana") ) -
.compareToIgnoreCase():忽略大小写的字典序比较,适合不敏感场景(如用户名校验)
高频字符串操作方法速查
日常处理中,这些方法用得最多,注意它们都返回新字符串,原字符串不变:
-
length():获取字符个数(不是字节数) -
charAt(i):获取索引i处的字符(索引从 0 开始,越界抛StringIndexOutOfBoundsException) -
substring(begin, end):截取[begin, end)区间(含头不含尾),单参数版本从 begin 到末尾 -
indexOf("str")/lastIndexOf("str"):查找子串首次/末次出现位置,没找到返回-1 -
replace(oldChar, newChar)或replace("old", "new"):替换所有匹配项(注意是生成新串,不是原地修改) -
trim():去除首尾空白字符(' '、'\t'、'\n'等),中间空格保留 -
split("regex"):按正则表达式切分,返回字符串数组(如"a,b,c".split(",")→["a","b","c"])
拼接字符串该用谁
简单拼接用 + 最直观,但循环中大量拼接时效率低(每次都会新建对象)。这时推荐:
-
StringBuilder:非线程安全,性能高,适合单线程场景(如方法内拼接) -
StringBuffer:线程安全(方法加了synchronized),适合多线程共享拼接 - 使用示例:
new StringBuilder().append("Hi").append(" ").append("World").toString()
编译器会对简单 + 做优化(如 "a" + "b" + "c" 直接合并为常量),但变量参与时(s1 + s2 + s3)仍会生成多个临时对象。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










