如何创建不可变的Java类或对象


  在学习编程的过程中,我觉得不止要获得课本的知识,更多的是通过学习技术知识提高解决问题的能力,这样我们才能走在最前方,本文主要讲述如何创建不可变的Java类或对象,更多Java专业知识,广州疯狂java培训官网与你分享;

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

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

  但有的时候String的immutable特性也会引起安全问题,这就是密码应该存放在字符数组中而不是String中的原因!

  immutable objects 比传统的mutable对象在多线程应用中更具有优势,它不仅能够保证对象的状态不被改变,而且还可以不使用锁机制就能被其他线程共享。

  实际上JDK本身就自带了一些immutable类,比如String,Integer以及其他包装类。为什么说String是immutable的呢?比如:java.lang.String 的trim,uppercase,substring等方法,它们返回的都是新的String对象,而并不是直接修改原来的对象。

  如何在Java中写出Immutable的类?

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

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

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

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

  4)对象应该是fianl的,以此来限制子类继承父类,以避免子类改变了父类的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对象会创造很大的价值。

  疯狂java是java培训行业的一匹黑马,专注于高级软件编程,疯狂java体系包括《疯狂Java讲义》、《疯狂Android讲义》、《轻量级Java EE企业应用实战》等著作。其中疯狂Java体系图书都是已经得到广泛的市场认同,并多次重印的畅销图书,并被多所高等院校选作教材。疯狂Java培训紧跟最前沿的技术潮流,采用的都是企业最真实的项目开发,培养学生的实践动手能力。技术在不断更新换代,在疯狂软件学院能学到最前沿的Java技术,疯狂Java培训主要培养的是Java专业人才,android专业人才。学员毕业之后的代码量至少达到项目经理的水平。疯狂软件学院有完善的就业服务机制,学员毕业时,可以享受免费终身推荐就业服务。根据学员的特点和企业的要求,为学员推荐最合适的岗位。

优质内容筛选与推荐>>
1、git学习笔记
2、软键盘挡住输入框问题的终极解决方案
3、hdu 3449
4、mysql的常用函数
5、聚类算法的评估


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号