通过快照图我们可以视图化可更改的值和可被重新赋值的改变之间的区别:
- 当你给一个变量或者一个区域(filed)赋值的时候,你实际上是改变了它指向的方向,即指向了另一个值。
- 当你修改一个可被更改的(mutable)值的时候——例如数组或者列表——你真正修改了这个值本身(译者注:变量或者区域的指向并没有变)
immutable
例如,如果我们有一个 String
变量 s
, 我们可以将它从 "a"
赋值为 "ab"
.
String s = "a";
s = s + "b";
String
就是一种不可改变的(immutable)值,这种类型的值在第一次确定后就不能改变。不可更改的对象(设计者希望它们一直是这个值)在快照图中以双圆圈的边框表示,例如上面的字符串对象。
mutable
与此相对应的, StringBuilder
(Java的一个内置类) 是一个可更改的字符串对象,它内置了许多改变其内容的方法:
StringBuilder sb = new StringBuilder("a");
sb.append("b");
可更改性和不可更改性(mutability and immutability)将会对我们的“安全健壮性”目标起到重要作用。
final
Java也提供了不可更改的引用:final
声明,变量一旦被赋值就不能再次改变它的引用(指向的值或者对象)。
如果Java编译器发现final
声明的变量在运行中被赋值多次,它就会报错。所以final
就是为不可更改的引用提供了静态检查。
在快照图中,不可更改的引用(final
)用双箭头表示,例如上图中的id
,Person
的id
引用不可改变,但是age却是可改变的。
这里要特别注意一点,final
只是限定了引用不可变,我们可以将其引用到一个可更改的值 (例如final StringBuilder sb
),虽然引用不变,但引用的对象本身的内容可以改变。
同样的,我们也可以将一个可更改的引用作用到一个不可更改的值(例如String s
),这个时候变量值的改变就是将引用改变。