字符串不可变性

String类中没有提供修改字符串中某个字符的方法。这点和php也不一样,php可以非常方便的修改字符串的任意位置的字符

$str = 'php';
$str[0] = 'P';

在Java中只能重新创建一个字符串

String str = "java";
str = "J" + str.substring(1);  // Java

通过字面量的方式(区别于new)给一字符串赋值,此时的字符串值保存在字符串常量池中,字符串变量则指向池中相应位置。

不可变字符串的优点是可以共享,当给一个字符串变量赋值时,发现字符串常量池中已有该值,那么就不用再重新创建字符串了。(字符串常量池中不会存储相同的字符串

var str1 = "abc"; // 会在字符串常量池中创建abc
var str2 = "abc";  // 常量池已有,不会再创建

System.out.println(str1 == str2); // true

当给str1赋值时,字符串常量池是没有“abc”字符串的,所以会在常量池中创建“abc”。创建完之后,将该字符串地址值(假设为0x1224)返回给str1。当给str2赋值时,系统发现常量池含”abc“字符串,不会重复创建而是直接把该字符串所在地址0x1224返回给str2。

下面,再通过一个例子来理解字符串的不可变性。

var str1 = "java"; 
var str2 = str1;
str2 = "c++";
System.out.println(str1);  // java

int[] arr1 = {1,3,5};
int[] arr2 = arr1;
arr2[0] = -1;
System.out.println(arr1[0]);  // -1

前两行代码执行完后,str1和str2指向同一个地址值。当执行第三行代码时,由于字符串的不可变性,所以原字符串常量池中的字符串java不会被修改,此时会在字符串常量池中重新创建一个新的字符串“c++”,然后将该地址值返回给str2。所以,str1的值仍旧为java。