`
810364804
  • 浏览: 779413 次
文章分类
社区版块
存档分类
最新评论

Java 不可变类

 
阅读更多


本文整理自《Effective Java》一书。


不可变类,并在对象的整个生命周期(lifetime)内保持不变。Java平台类库中包含许多不可变的类,其中有String、基本类型的包装类、BigInteger、BigDecimal

为了使类成为不可变,要遵循下面五条规则:

1.不要提供任务会修改对象状态的方法。

2.保证类不会被扩展。常见做法final Class、 private constructor并添加公有的静态工厂(static factory)来代替公有的构造器,如 public static Complex valueOf(){ return new Complex();}。

3.使所有的域都是final的。final

4.使所有的域都成为私有的。private

5.确保对于任何可变组件的互斥访问。采用函数的(functional)做法,防止this引用逸出,如String中的做法:

public static String copyValueOf(char data[]) {
        return new String(data);
}

不可变对象本质上是线程安全的,它们不要求同步。当多个线程并发访问这样的对象时,它们不会遭到破坏,所以,不可变对象可以被自由的共享。不可变类应该充分利用这种优势,鼓励客户端尽可能地重用现有的实例,对于频繁用到的值,为它们提供公有的static final 常量,如 Integer 提供的 public static final intMIN_VALUE =-231


不可变类的真正唯一的缺点是,对于每个不同的值都需要一个单独的对象。创建这种对象的代价可能很高,特别是对于大型对象的情形。所以,最好的办法是提供一个公有的可变配套类。在Java平台类库中,这种方法的主要例子是String类,以及它的可变配套类StringBuilder(和基本上已经废弃的StringBuffer)


当BigInteger和BigDecimal刚被编写出来的时候,对于“不可变的类必须为final的”还没有得到广泛地理解,所以它们的所有方法都可能被覆盖,遗憾的是,为了保持向后兼容,这个问题一直无法得以修正。

public class BigDecimal
extends Number
implements Comparable<BigDecimal>

如果你在编写一个类,它的安全性依赖于BigInteger或者BigDecimal参数的不可变性,就必须进行检查,以确定这个参数是否为“真正的”BigInteger或者BigDecimal,而不是不可信任子类的实例。如果是后者的话,就必须在假设它可能是可变的前提下对它进行保护性拷贝:

public static BigInteger safeInstance(BigInteger val){
	if(val.getClass()!= BigInteger.class){
		return new BigInteger(val.toByteArray());
	}
	return val;
}

实际中,上述规则规定不可变类的所有域都必须是final的。这个要求为了提高性能可以有所放松,只要没有一个方法能够对对象的状态产生外部可见的改变。如String类的

/** Cache the hash code for the string */private int hash; 采用延迟初始化来缓存一些开销昂贵的计算结果到这些域中

除非有令人信服的理由要使域变成是非final的,否则要使每个域都是final的。关于final域:"When final is used withobject references rather than primitives, the meaning can be confusing. With aprimitive, final makes the value a constant, but with an object reference,final makes the reference a constant. Once the reference is initialized to anobject, it can nerver be changed to point to another object. However, theobject itself can be modified." FromThinking in Javafinal修饰域时,只保证引用的不可变,而不保证引用指向的对象不可变,除非这个对象本身是不可变。请一定确保公有类的公有static final域所引用的对象都是不可变的



分享到:
评论

相关推荐

    Java不可变类机制浅析

    所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值。如JDK内部自带的很多不可变类:Interger、Long和String等。接下来通过本文给大家介绍Java不可变类机制,需要的朋友参考下

    JAVA不可变类(immutable)机制与String的不可变性(推荐)

    主要介绍了JAVA不可变类(immutable)机制与String的不可变性(推荐)的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下

    Java String类为什么是不可变的_动力节点Java学院整理

    Java String类为什么是不可变的_动力节点Java学院整理,动力节点口口相传的Java黄埔军校

    浅谈为什么Java里面String类是不可变的

    主要介绍了为什么Java里面String类是不可变的,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    Java如何创建不可变类

     不可变类:当你获得这个类的一个实例引用时,你不可以改变这个实例的内容。  那么,什么是不可变对象?  一旦一个类的实例化对象被创建并初始化,那么它不可以被改变。我们可以调用访问器方法(getter),...

    如何在 Java 中实现不可变类

    主要介绍了如何在 Java 中实现不可变类,不变性是函数式编程的关键,因为它与尽量减少变化部分的这一目标相一致,这使得对这些部分的推断更为容易一些。,需要的朋友可以参考下

    java_JTextArea_实现不可修改文本内容、右键菜单

    JavaSwing JTextArea 实现不可修改文本内容、右键菜单定制

    深入Java不可变类型的详解

    本篇文章是Java中的不可变类型进行了详细的分析介绍,需要的朋友参考下

    Java编程学习之java的不可变数据结构.doc

    Java编程学习之java的不可变数据结构.doc

    Java中如何实现不可变Map详解

    主要给大家介绍了关于Java中如何实现不可变Map的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作工具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    Java String 类.pdf

    String类是不可变的,一旦创建了一个字符串对象,就无法修改它。而StringBuilder类是可变的,可以在缓冲区中修改字符串,而不必创建新的对象。 另一个区别在于性能。由于String类是不可变的,对字符串进行操作时需要...

    Java不可变对象整洁之道

    在 Java 语言中,不可变类指的是这个类的实例是不可修改的,在创建类实例时我们需要指定这个类所有的属性值,而且在以后的生命周期中这些属性值都不能重新赋值。经验丰富的你可能已经知道 Java 中已经存在一些不可变...

    换个角度理解Java中的不可变集合.docx

    为什么要使用不可变集合 不可变对象有很多优点,包括: 当对象被不可信的库调用时,不可变形式是安全的; 不可变对象被多个线程调用时,不存在竞态条件问题 不可变集合不需要考虑变化,因此可以节省时间和空间...

    java properties文件操作工具类,可追加修改

    此工具类只用于Java后端在操作Properties文件的时候写的工具类,方便properties文件的存取操作

    java-immutable-collections:Java不可变的基于数组的集合

    ImmutableCollections-基于数组的Java不可变集合 版权所有(c)2017 Nicholas Cull 有关许可信息,请参阅LICENSE.txt。 Java 1.8的基于数组的不可变集合 排序和未排序的变体 风格类似于番石榴收集包装 空友好 Java 8...

    java邮件读取工具类,可读取附件,功能强大!

    java邮件读取工具类,可读取附件,功能强大,经测试可用。

    Java中的String对象是不可变的吗Java开发Jav

    Java中的String对象是不可变的吗Java开发Java经验技巧共4页.pdf.zip

    java swing 表头不可拖动

    java swing 表头不可拖动 基础篇 我根据课程慢慢上传的 适合初学者 实用的好东西 大家快来呀!!!

    JavaClassImmutable:Java类不可变

    JavaClassImmutable Java类不可变不可变对象是那些一旦创建便无法更改状态的对象,例如String类是不可变类。 不变的对象不能被修改,因此它们在并发执行中也是线程安全的。不变类的特征: 构造简单。 自动线程安全。...

Global site tag (gtag.js) - Google Analytics