不可变对象

2018-08-22  本文已影响0人  mrjunwang

https://www.cnblogs.com/jaylon/p/5721571.html

  1. 类添加final修饰符,保证类不被继承。
    如果类可以被继承会破坏类的不可变性机制,只要继承类覆盖父类的方法并且继承类可以改变成员变量值,那么一旦子类以父类的形式出现时,不能保证当前类是否可变。

  2. 保证所有成员变量必须私有,并且加上final修饰
    通过这种方式保证成员变量不可改变。但只做到这一步还不够,因为如果是对象成员变量有可能再外部改变其值。所以第4点弥补这个不足。

  3. 不提供改变成员变量的方法,包括setter
    避免通过其他接口改变成员变量的值,破坏不可变特性。

4.通过构造器初始化所有成员,进行深拷贝(deep copy)

如果构造器传入的对象直接赋值给成员变量,还是可以通过对传入对象的修改进而导致改变内部变量的值。
String对象的不可变性的优缺点
从上一节分析,String数据不可变类,那设置这样的特性有什么好处呢?我总结为以下几点:

1.字符串常量池的需要.
字符串常量池可以将一些字符常量放在常量池中重复使用,避免每次都重新创建相同的对象、节省存储空间。但如果字符串是可变的,此时相同内容的String还指向常量池的同一个内存空间,当某个变量改变了该内存的值时,其他遍历的值也会发生改变。所以不符合常量池设计的初衷。

  1. 线程安全考虑。
    同一个字符串实例可以被多个线程共享。这样便不用因为线程安全问题而使用同步。字符串自己便是线程安全的。

  2. 类加载器要用到字符串,不可变性提供了安全性,以便正确的类被加载。譬如你想加载java.sql.Connection类,而这个值被改成了myhacked.Connection,那么会对你的数据库造成不可知的破坏。

  3. 支持hash映射和缓存。
    因为字符串是不可变的,所以在它创建的时候hashcode就被缓存了,不需要重新计算。这就使得字符串很适合作为Map中的键,字符串的处理速度要快过其它的键对象。这就是HashMap中的键往往都使用字符串

上一篇下一篇

猜你喜欢

热点阅读