不可变对象(immutable objects),后面文章我将使用immutable objects来代替不可变对象!

那么什么是immutable objects?什么又是mutable Objects呢?

immutable Objects就是那些一旦被创建,它们的状态就不能被改变的Objects,每次对他们的改变都是产生了新的immutable的对象,而mutable Objects就是那些创建后,状态可以被改变的Objects.

举个例子:String和StringBuilder,String是immutable的,每次对于String对象的修改都将产生一个新的String对象,而原来的对象保持不变,而StringBuilder是mutable,因为每次对于它的对象的修改都作用于该对象本身,并没有产生新的对象。

但有的时候String的immutable特性也会引起安全问题,这就是如何在Java中写出Immutable的类?

要写出这样的类,需要遵循以下几个原则:

1)immutable对象的状态在创建之后就不能发生改变,任何对它的改变都应该产生一个新的对象。

2)Immutable类的所有的属性都应该是final的。

3)对象必须被正确的创建,比如:对象引用在对象创建过程中不能泄露(leak)。

4)对象应该是final的,以此来限制子类继承父类,以避免子类改变了父类的immutable特性。

5)如果类中包含mutable类对象,那么返回给客户端的时候,返回该对象的一个拷贝,而不是该对象本身(该条可以归为第一条中的一个特例)

当然不完全遵守上面的原则也能够创建immutable的类,比如String的hashcode就不是final的,但它能保证每次调用它的值都是一致的,无论你多少次计算这个值,它都是一致的,因为这些值的是通过计算final的属性得来的!

另外,如果你的Java类中存在很多可选的和强制性的字段,你也可以使用建造者模式来创建一个immutable的类。

下面是一个例子:

public final class Contacts { private final String name; private final String mobile; public Contacts(String name, String mobile) { this.name = name; this.mobile = mobile; } public String getName(){ return name; } public String getMobile(){ return mobile; }}

我们为类添加了final修饰,从而避免因为继承和多态引起的immutable风险。上面是最简单的一种实现immutable类的方式,可以看到它的所有属性都是final的。

有时候你要实现的immutable类中可能包含mutable的类,比如java.util.Date,尽管你将其设置成了final的,但是它的值还是可以被修改的,为了避免这个问题,我们建议返回给用户该对象的一个拷贝,这也是Java的最佳实践之一。下面是一个创建包含mutable类对象的immutable类的例子:

public final class ImmutableReminder{ private final Date remindingDate; public ImmutableReminder (Date remindingDate) { if(remindingDate.getTime() < System.currentTimeMillis()){ throw new IllegalArgumentException("Can not set reminder” + “ for past time: " + remindingDate); } this.remindingDate = new Date(remindingDate.getTime()); } public Date getRemindingDate() { return (Date) remindingDate.clone(); }}

上面的getRemindingDate()方法可以看到,返回给用户的是类中的remindingDate属性的一个拷贝,这样的话如果别人通过getRemindingDate()方法获得了一个Date对象,然后修改了这个Date对象的值,那么这个值的修改将不会导致ImmutableReminder类对象中remindingDate值的修改。使用Immutable类的好处:

1)Immutable对象是线程安全的,可以不用被synchronize就在并发环境中共享

2)Immutable对象简化了程序开发,因为它无需使用额外的锁机制就可以在线程间共享

3)Immutable对象提高了程序的性能,因为它减少了synchroinzed的使用

4)Immutable对象是可以被重复使用的,你可以将它们缓存起来重复使用,就像字符串字面量和整型数字一样。你可以使用静态工厂方法来提供类似于valueOf()这样的方法,它可以从缓存中返回一个已经存在的Immutable对象,而不是重新创建一个。

immutable也有一个缺点就是会制造大量垃圾,由于他们不能被重用而且对于它们的使用就是”用“然后”扔“,字符串就是一个典型的例子,它会创造很多的垃圾,给垃圾收集带来很大的麻烦。当然这只是个极端的例子,合理的使用immutable对象会创造很大的价值。

immutable object?要做到下面几点

不提供setter

设置类为final,使其不被子类化。

设置所有成员变量(域)为final和private,防止直接修改。

如果某些成员变量是immuable的,那这些变量一定不能被外界访问到。如果要访问,要使用保护性拷贝来复制一份传给外界。

如果一个对象必须是mutable有什么需要注意的吗?

在函数传递参数时,必须是用保护性拷贝。就是说,无论是使用外界传入的参数,还是向外界返回结果,如果参数和结果是mutable的,必须拷贝一份再使用或者传出。这样子可以保证我这个对象的内部成员是不会因为外界的不经意的或者恶意的操作而发生变化。面向对象的核心之一就是数据的封装性。一个对象封装了内部状态,并公开了一些方法以操作或获取这些状态。对状态的改变只能通过该对象自己的方法,而不能是其他对象的操作的副产品。所以对于mutable object,保护性拷贝是必须的。现实中很多非常难以调试的bug,都是因为一个对象的状态被遥远的另外一个对象所改变,这种蝴蝶效应类的bug特别难调试。

在多线程环境中,如果一定要共享mutalbe object,那一般都加锁来确保同步。所以最好让mutable object限制在一个线程中使用,让其计算出的immuable object来共享,尽量减少两个线程同时读写同一个变量的可能性。如果一定要共享mutable object,那比较好的方式是在该对象中进行加锁等同步操作,而不是让外界调用者来自己同步,这样的对象也是线程安全的

mutable Java,不可变(Immutable)和mutable Objects的Java类或对象相关推荐

  1. java作业 大蛇丸的召唤术 万蛇罗之阵 类与对象的演练

    java作业 大蛇丸的召唤术 万蛇罗之阵 类与对象的演练 召唤刃类 public class Blade {String name;public void assassination() {Syste ...

  2. Java常用知识点汇总(基础:数组,类与对象,接口与继承)

    目录 数组 1.引用 2.增强型for循环 3.复制数组 arraycopy() 4.针对数组的工具类 Arrays 5.选择法排序 6.冒泡排序 7.练习-二维数组中的查找(剑指offer) 类与对 ...

  3. java oop概念_JAVA OOP(一)——OOP概念,类与对象

    OOP概念,类与对象 OOP--面向对象编程 类与对象 类 对象 OOP--面向对象编程 首先,我们来举一个例子: 现在我要用用代码实现下列要求,定义一只猫,它的名字叫"小芳",年 ...

  4. 转载---编写高质量代码:改善Java程序的151个建议(第3章:类、对象及方法___建议41~46)...

    阅读目录 建议41:让多重继承成为现实 建议42:让工具类不可实例化 建议43:避免对象的浅拷贝 建议44:推荐使用序列化对象的拷贝 建议45:覆写equals方法时不要识别不出自己 建议46:equ ...

  5. java基础,没事常看看(一)类、对象、引用

    什么是对象,什么是类? 类:是一个抽象的概念,表示的是一类事物所拥有的共性(属性.方法). 对象:是类的具体(实例),对象不仅拥有类的属性和方法(private除外),还有自己专属的属性与方法. 比如 ...

  6. 编写高质量代码:改善Java程序的151个建议(第3章:类、对象及方法___建议36~40)

    建议36:使用构造代码块精简程序 什么叫做代码块(Code Block)?用大括号把多行代码封装在一起,形成一个独立的数据体,实现特定算法的代码集合即为代码块,一般来说代码快不能单独运行的,必须要有运 ...

  7. 转载---编写高质量代码:改善Java程序的151个建议(第3章:类、对象及方法___建议47~51)...

    阅读目录 建议47:在equals中使用getClass进行类型判断 建议48:覆写equals方法必须覆写hashCode方法 建议49:推荐覆写toString方法 建议50:使用package- ...

  8. 转载--编写高质量代码:改善Java程序的151个建议(第3章:类、对象及方法___建议31~35)...

    阅读目录 建议31:在接口中不要存在实现代码 建议32:静态变量一定要先声明后赋值 建议33:不要覆写静态方法 建议34:构造函数尽量简化 建议35:避免在构造函数中初始化其它类 书读的多而不思考,你 ...

  9. java是什么 需要学什么_Java是什么,Java需要学习哪些内容?如何自学Java?

    Java作为一种通用的编程语言可以做很多事情,但怎么学Java就看怎么用了,很多初学者想通过埋头苦学.马不停蹄的敲着代码记住Java基本原理,但一遇到困难便会让自己发狂,种种坎坷将自己打回原形. 为了 ...

  10. java类和对象在内存的表现形式

    Java内存分配与管理是Java的核心技术之一,不管学习任何一门语言,我们要知其然,知其所以然,本文主要分析下Java中类和对象在内存中的表现形式,方便我们对其有更深了解.一般Java在内存分配时会涉 ...

最新文章

  1. 蓝牙(BLE)应用框架接口设计和应用开发——以TI CC2541为例
  2. native-maven-plugin与maven-nar-plugin配置
  3. 三部排序|2013年蓝桥杯B组题解析第六题-fishers
  4. How does SAP OData framework interpret $expand=Notes
  5. 我国在量子计算机领域的发展情况的感受,量子计算机的现状及发展趋势.doc
  6. ChatForFun 公众号使用说明
  7. c语言转换为python语言_python和c语言
  8. C++之第一个程序Hello World,使用IO库输出Hello World
  9. TCP三次握手四次挥手(图解)
  10. SQL 行转列、列转行
  11. SQL Server-【知识与实战I】条件查询、比较运算符查询、模糊查询、枚举查询、范围查询、空值查询、多重条件查询
  12. [转]vs2003,安装程序检测到另一个程序要求计算机重新启动
  13. winform通过restsharp调用api接口登录及其它接口
  14. 黑苹果10.13.6及以下安装WebDriver驱动nvidia独立显卡,以及修改机型
  15. 领导与管理的区别与联系
  16. Unity制作Roll-a-Ball游戏
  17. 软考·系统架构师论文——论软件的高并发设计
  18. 有测试智商的软件不,测试智商的软件有哪些
  19. jeecg-boot自动生成代码_PSIM 仿真:如何使用 PSIM12 自动生成代码
  20. linux和Windows线程进程的区别

热门文章

  1. 网上办卡,你关注“合约期”了吗?
  2. JS/Jquery常用代码
  3. python设置制表符的长度_Python展开制表符长度计算
  4. 中国人自己的编程语言——T语言
  5. IDS和IPS部署位置
  6. 黑马——广告条效果(利用ViewPager实现)
  7. js 如何代替java中的长整型_Javascript长整型
  8. 怎么下载python3.5.2_Python3.5.2
  9. 一份非常详细的MongoDB数据库基本常用命令总结(文档基本CRUD +其他常用查询)
  10. private访问权限java_Java中的访问权限控制