String 类的不可变性

今天在 String 是发现 String 在 Java 中非常有趣。首先,String 是不可变的,当我们修改 String 的对象时,并不是在原对象上进行修改,而是新建一个 String 对象,并指向这个对象。

1
2
3
4
5
6
7
8
9
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence,
Constable, ConstantDesc {

...
@Stable
private final byte[] value;

}

String 类的使用 privatefinal 关键字修饰存放字符的数组,且没有提供修改数组的方法。

final 关键字修饰类无法被继承,修饰的方法不能被重写,修饰的基本数据类型的值无法更改,修饰的引用类型无法修改地址。final 修饰数组不是 String 不可变的根本原因,因为 final 修饰下的数组地址不可改变,而其中的值仍然可以改变。

1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) throws Exception {
String s = "aaa";
_appendString_(s);
System._out_.println("String aaa >>> "+s);
}

public static void appendString(String s){
s += "bbb";
}

//String aaa >>> aaa

像在以上的情况下,由于 String 的不可变性,对 String 的修改会让 String 指向一个新的地址,而 Java 是值传递语言,方法中对 String 的改变只改变了形参 S 的地址,并没有改变实参 S 的地址。

String地址改变的示例图片