1.3 快照图(Snapshot diagram)... 4
数据类型:一组值以及可以对其执行的操作。
变量:用特定数据类型定义,可存储满足类型约束的值。
改变变量和值的区别
改变一个变量:将该变量指向另一个值的存储空间。
改变一个变量的值:将该变量当前指向的值的存储空间中写入一个新的值。
不变性
不变数据类型(immutable type):一旦被创建,其值不能改变。
引用不变:一旦确定其指向的对象,不能再被改变(但其值是可能变化的)。
Java中的final关键字
final类无法派生子类;
final方法无法被子类重写;
final变量无法改变其引用(而非值)。
可变类型(mutable)
拥有方法可以修改自己的值。
不可变类型(immutable)
一旦被创建,就始终代表(对外表现出)同样的值。
区别
当只有一个引用指向该值, 可变类型和不可变类型并没有大的区别,但有多个引用的时候,差异就出现了。
保护可变类型
防御式拷贝:给客户端返回一个全新的对象。大部分时候该拷贝不会被客户端修改可能造成大量的内存浪费。
单引用局部变量:把对mutable对象的引用限制在类/方法内,不对外暴露。如果存在多个引用,使用可变类型就非常不安全。
快照图在三维视图中属于运行时、瞬时、代码级视图。
基本类型
在箭头末端填写值。
对象类型
在箭头末端画一个椭圆,在其中写上对象的类名,更详细的话再包含内部属性。
可变类型对象的椭圆使用单线,而不可变类型的椭圆使用双线。
引用
可变引用使用单线,不可变引用使用双线。
经典的容器有数组、list、set、map等。数组是固定长度的序列,而其他容器长度可变。
迭代器
迭代器是一个可变数据类型,它拥有两个方法:next()返回容器的下一个数据; hasNext()返回容器是否还有下一个数据。
基本类型及其封装对象类型都是不可变的,高精度数 BigInteger 和 BigDecimal 也是不可变的。
不要使用 Date,因为它是可变类型。相反,使用 java.time 包下的类,如 LocalDateTime。
Java 中的常用容器如 ArrayList、HashMap 等都是 mutable 的,如果希望容器不可变,可使用包装器 Collections.unmodifiableList 等获取一个不可变的包装对象——当调用 mutator 方法时会抛出一个异常。
然而,这种“不可变”是在运行阶段获得的,编译阶段无法据此进行静态检查。同时,wrapper 仅仅保证了无法通过 wrapper 引用修改对象,但如果通过被包装对象的引用修改了对象的值,wrapper 引用指向的对象仍然会被修改。