Java字符串何时可修改?两段代码修改结果差异原因解析
Java字符串的“修改”真相
Java里的String是不可变类型——一旦创建,它内部的字符内容就再也没法改变。我们平时说的“修改字符串”,本质都是生成了新的String对象,然后让原来的变量重新指向这个新对象。常见的“修改”场景包括:
- 用
+拼接字符串时,每次拼接都会产生新的字符串对象 - 调用
substring()、replace()、toUpperCase()这类String方法时,这些方法不会改动原字符串,只会返回一个全新的字符串实例 - 如果要真正在原容器里修改字符序列,得用
StringBuilder或StringBuffer,它们的append()、insert()等方法可以直接修改内部的字符数组,最后通过toString()转成String对象
为什么两个版本输出不一样?
版本1的执行逻辑
在版本1的main方法里,这句代码:
str = str.substring(2, 3) + str.substring(1, 2) + str.substring(0, 1);
substring和+操作生成了新的字符串"orF",然后直接把main方法里的局部变量str改成指向这个新对象。后面打印的时候,自然输出的是新对象的内容。
版本2的问题根源
版本2里调用了processString(str),这里要搞懂Java的参数传递规则:Java里所有参数传递都是值传递。当你把main里的str传给processString时,传递的是原字符串引用的一个副本——也就是说,processString方法里的str是一个单独的局部变量,只是和main里的str指向同一个"Frog"对象而已。
在processString里,你把这个局部的str重新指向了新生成的"orF",但这只会改变方法内部这个局部变量的指向,完全影响不到main方法里原来的str。所以main里的str还是指向最初的"Frog",打印出来当然还是它。
让版本2生效的两种方式
- 让
processString返回新字符串,在main里接收:
public static void main(String[] args) { String str = "Frog"; str = processString(str); // 把返回的新对象赋值给原变量 System.out.println(str); } public static String processString (String str) { return str.substring(2, 3) + str.substring(1, 2) + str.substring(0, 1); }
- 用
StringBuilder这种可变容器当参数(因为它是引用类型,修改内部状态会同步到原对象):
public static void main(String[] args) { StringBuilder str = new StringBuilder("Frog"); processString(str); System.out.println(str); } public static void processString (StringBuilder str) { String newStr = str.substring(2, 3) + str.substring(1, 2) + str.substring(0, 1); str.replace(0, str.length(), newStr); }
内容的提问来源于stack exchange,提问作者EthanAlvaree
相关产品推荐
相关产品推荐

