如何在Java中写出Immutable的类?

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

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

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

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

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

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

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

下面是一个例子:

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对象会创造很大的价值。

转载于:https://www.cnblogs.com/gdjdsjh/p/5111083.html

关于java中的不可变类(转)相关推荐

  1. setyear java_如何在Java中创建不可变类

    如果对象在构造后无法更改,则该对象是不可变的.不可变对象不会以任何方式暴露其他对象来修改其状态; 对象的字段仅在构造函数内初始化一次,并且永远不会再次更改. 在本文中,我们将定义在Java中创建不可变 ...

  2. java创建一个不可变对象_如何在Java中创建不可变类?

    java创建一个不可变对象 Today we will learn about the immutable class in Java. What are immutable classes? The ...

  3. Java中的不可变类

    随时随地技术实战干货,获取项目源码.学习资料,请关注源代码社区公众号(ydmsq666) 概念:不可变类的意思是创建该类的实例后,该实例的属性是不可改变的.java中的8个包装类和String类都是不 ...

  4. JAVA中常量使用常量类或者常量接口还是使用枚举,错误代码和中文可变信息的枚举实现

    文章目录 关于"JAVA中常量使用常量类或者常量接口还是使用枚举",已有定论-使用枚举,原因就不再展开了. 借助java枚举,可以在定义错误名称和代码的同时,定义中文描述信息,但是 ...

  5. 深入理解Java中的不可变对象

    二哥,你能给我说说为什么 String 是 immutable 类(不可变对象)吗?我想研究它,想知道为什么它就不可变了,这种强烈的愿望就像想研究浩瀚的星空一样.但无奈自身功力有限,始终觉得雾里看花终 ...

  6. Java中通过代理对类进行修改

    JAVA中的静态代理.动态代理及JDK proxy和CGLIB.Javassist.ASM实践 简介 Java中对已经有的类进行修改,改变或调整其执行,这可以通过代理来实现.Java的class文件是 ...

  7. java中的starts_Java Math类静态double nextAfter(double starts,double direction)示例

    java中的starts 数学类静态double nextAfter(双向启动,双向) (Math Class static double nextAfter(double starts , doub ...

  8. Java中Date和Calender类的使用方法

    查看文章     Java中Date和Calender类的使用方法 2009-10-04 20:49 Date和Calendar是Java类库里提供对时间进行处理的类,由于日期在商业逻辑的应用中占据着 ...

  9. 《Java并发编程的艺术》——Java中的并发工具类、线程池、Execute框架(笔记)

    文章目录 八.Java中的并发工具类 8.1 等待多线程完成的CountDownLatch 8.2 同步屏障CyclicBarrier 8.2.1 CyclicBarrier简介 8.2.2 Cycl ...

最新文章

  1. iis5.1配置php5.3.1详解,WinXP IIS 5.1 PHP 5.3 VC9.0 配置详解
  2. Javascript的数据结构与算法(一)
  3. python 如何把小数变成百分数格式
  4. 如何下载和安装SQL Server数据库实验助手(DEA v2.0)
  5. java 找出调用的方法_如何找到用Java调用给定方法的所有方法?
  6. Ubuntu18.04取消VIM自动备份文件
  7. 魔兽世界服务器修改模型,修改模型教程!
  8. C++ 小游戏 视频及资料集(9)
  9. kaptcha生成自定义图片验证码
  10. 在wamp 或者xamp 下测试多个独立的网页文件
  11. 【软件测试】——软件测试经验总结
  12. 【DBC专题】-4-DBC文件中的Signal信号字节顺序Motorola和Intel介绍
  13. 哪款蓝牙耳机耳朵不疼?久戴不疼的骨传导耳机
  14. h标签本身自带间距 去除方法
  15. 【数据库】数据库基本知识
  16. 2020-01-08 Oracle 数据库储存生僻字
  17. 360年会三娘逆袭 女程序员戴假发化妆成-搜狐滚动
  18. InDesign插件--常规功能开发--版面调整--js脚本开发--ID插件
  19. 面试-Senior Specialist for Devops-车企
  20. Spring IoC的理解----找女朋友的方法

热门文章

  1. Vivado HLS error: Cannot find ISE in the PATH variable or it's an unsupported version
  2. SQLite主键自增需要设置为integer PRIMARY KEY
  3. ubuntu11.04中如何像其他版本一样快速回到桌面
  4. poj 2891 Strange Way to Express Integers 2012-09-05
  5. 盘点机器学习和统计模型的差异
  6. JavaScript 同源策略
  7. Silverlight与WPF中BeginInvoke的差异
  8. Silverlight 参考:三维效果(透视转换) -- MSN
  9. 转载:浅谈软件测试流程
  10. soap 版本可能不匹配: 出现意外的 envelope 命名空间_Collaboratorv11.5版本上新!GitHub Polling集成被弃用!...