谈谈Mutability and Immutability(可变数据型和不可变数据型)

可变型(Mutability):当这个对象指向一个实例的时候,可以对对象里面的实例进行修改

不可变型(Immutability):当得到一个对象的实例时,你不可以改变这个实例的内容。不可变类的实例一但创建,其内在成员变量的值就不能被修改。

final:我们可以用final关键字来将一个数据对象变为Immutability类型的。但是注意,如果使用了final关键字,它里面的内容还有可能发生变化。因为final关键字只是将这个指针固定,而指针里面的内容发生改变的时候,它也无能为力。例如:

使用final来修饰StringBuilder(可变型)类型的对象的时候,final StringBuilder s = new StringBuilder("aa");然后扩展字符串,s.append("b");得到如下结果:

谈谈Mutability and Immutability(可变数据型和不可变数据型)

说明利用final关键字也不见得一定不能使数据改变。

接下来利用String和StringBuilder来谈谈可变型和不可变型的差异:

String(Immutability):例如有如下的代码:

谈谈Mutability and Immutability(可变数据型和不可变数据型)

那么画出它的snapshot图的话,就是如下:

谈谈Mutability and Immutability(可变数据型和不可变数据型)

这就可以看出来String对象里面的数据被改变的时候,会在内存里面新建一个另外的对象,将改变过后的数据加入到这个新对象里面,然后修改引用即可。

而对于StringBuilder(Mutability),假设有代码:

谈谈Mutability and Immutability(可变数据型和不可变数据型)

同样的画出它的snapshot图:

谈谈Mutability and Immutability(可变数据型和不可变数据型)

我们就可以看出来他们之间的差别了,不可变类型StringBuilder的值改变的时候,是里面的数据发生相应的改变,而对象的引用关系没有发生变化,即内存地址没有变化。

两者优缺点:

mutable(可变型)和immutable(不可变型):

当有多个对象同时指向同一个实例的时候,如果使用不可变型的话,那么实例里面的内容可能被修改,那么所有的指向该实例的对象都发生了改变,这就会导致其他类调用数据的时候发生错误,而且很难发觉。

但是,使用不可变类型,对其频繁修改会产生大量的临时拷贝(需要垃圾回收),因此,内存的占用也是不可避免的。

如果使用可变类型的话,那么可变类型可以最少化拷贝以提高效率。例如下面的这个例子:

谈谈Mutability and Immutability(可变数据型和不可变数据型)

谈谈Mutability and Immutability(可变数据型和不可变数据型)

这个函数主要就是将一个字符串扩展大n个数。如果使用String的话,那么每次循环,都会新建一个对象并将原来的对象拷贝进去,而且还会有垃圾留在内存当中,那么如果n的值足够大的话,它的时间消耗和内存消耗都是巨大的。所以在使用这两种类型的时候,要注意性能和正确性的结合,有所取舍。