在多线程学习系列 - 2 - Immutable Pattern
中,作者告诉我们不可变类的好处以及如何设计不可变类
下面的内容是Effective Java(v2)中的第15条--使4可变性最小化
作者给出了设计不可变类的一些建议,多线程学习系列 - 2 - Immutable Pattern
中一些建议过于强硬,比如类要是final,域要是final等等
1.不要提供任何会修改对象状态的方法
2.保证类不会被扩展(final类)
可以防止粗心或恶意的子类假装对象的状态已经改变,从而破坏该类的不可变行为
3.使所有的域都是final的
4.使所有的域都是私有的
防止客户端直接修改这些对象
5.确保对于任何可变组件的互斥访问
如果类具有指向可变对象的域,则必须确保该类的客户端无法获得这些对象的引用
永远不要用客户端提供的对象引用来初始化这样的域
也不要从任何访问方法中返回该对象引用
在构造器,访问方法和readObject方法中使用保护性拷贝
effective java中给了一个例子
Complex为复数,具有实部和虚部
public final class Complex {
private final double re;
private final double im;
public Complex(double re, double im) {
this.re = re;
this.im = im;
}
public static final Complex ZERO = new Complex(0, 0);
public static final Complex ONE = new Complex(1, 0);
public static final Complex I = new Complex(0, 1);
// Accessors with no corresponding mutators
public double realPart() { return re; }
public double imaginaryPart() { return im; }
public Complex add(Complex c) {
return new Complex(re + c.re, im + c.im);
}
public Complex subtract(Complex c) {
return new Complex(re - c.re, im - c.im);
}
public Complex multiply(Complex c) {
return new Complex(re * c.re - im * c.im,
re * c.im + im * c.re);
}
public Complex divide(Complex c) {
double tmp = c.re * c.re + c.im * c.im;
return new Complex((re * c.re + im * c.im) / tmp,
(im * c.re - re * c.im) / tmp);
}
@Override public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Complex))
return false;
Complex c = (Complex) o;
return Double.compare(re, c.re) == 0 &&
Double.compare(im, c.im) == 0;
}
@Override public int hashCode() {
int result = 17 + hashDouble(re);
result = 31 * result + hashDouble(im);
return result;
}
private int hashDouble(double val) {
long longBits = Double.doubleToLongBits(re);
return (int) (longBits ^ (longBits >>> 32));
}
@Override public String toString() {
return "(" + re + " + " + im + "i)";
}
}
下面分析下复数这个类
它是final的,成员变量均为private final
除了构造函数,没有任何能够改变自己状态的方法
构造函数的参数为double,也是不可变的
有几个方法是返回Complex,注意这些方法,他们无一不是new一个新Complex,并没有修改自身
所以Complex是不可变的
不可变对象可以自由的被共享
我们应该尽量的重用现有实例,所以对于频繁使用的值应该提供public final的常量
例如:
public static final Complex ZERO = new Complex(0,0);
public static final Complex ONE = new Complex(1,0);
public static final Complex I = new Complex(0,1);
我们还可以进一步扩展一下想法,给它提供一个静态工厂方法
,这样可以更灵活的控制缓存,自己选择是否创建新的实例
静态工厂有许多优势,举例来说:假如你想以极坐标的方式创建一个复数,那么构造函数可能会是下面这样
public Complex(double re, double im){...}
可是已经有了一个相同签名的构造函数了,所以这样是不行的
而使用静态工厂,你就可以更改签名了,例如下面这样
public static Complex valueOfPolar(double r, double theta) {
return new Complex(r * Math.cos(theta),
r * Math.sin(theta));
}
不可变对象无须任何拷贝,所以也不用提供clone或者拷贝构造器
ps:听说这点在java平台的早期不好理解,所以String还保留了拷贝构造器
不可变对象还可以共用内部信息
BigInteger中的一个例子
在它的negate方法中新建另一个对象,数值是一样的,符号是相反的,并没有拷贝数组
final int[] mag;
public BigInteger negate() {
return new BigInteger(this.mag, -this.signum);
}
对于第二条保证类不会被扩展(final类)
,可以不用那么严格,不一定非要是final类才可以
我们把所有的构造函数设置为private,通过静态工厂创建实例,那么也一样可以达到final类的效果
添加如下方法即可
public static Complex valueOf(double re, double im) {
return new Complex(re, im);
}
对于第三条使所有的域都是final的
,也可以不用那么严格
只要没有一个方法能够对对像的状态产生外部可见的改变就可以
这些非final域在第一次被请求执行计算这些计算结果的时候把一些开销昂贵的计算结果缓存在这些域中达到复用,因为对象是不可变的,所以每次请求返回的结果一致
转贴请保留以下链接
本人blog地址
http://su1216.iteye.com/
http://blog.csdn.net/su1216/
分享到:
相关推荐
前端开源库-immutable-require-valid-log-client不可变要求有效的日志客户端,不可变的日志客户端验证函数
前端开源库-immutable-require-valid-optional-object不可变要求有效的可选对象,如果参数不是对象,则返回空对象或引发异常
websocket即时聊天工具前端技术栈:react+redux+immutable.js+Material-Ui后端技术栈:koa2+mysqlnpm start 前端项目启动npm service 后端服务启动npm run build 项目打包tips:本地开发,先 npm run server 启动后端...
Immutable.js-处理不可变数据的技术:waving_hand_medium-light_skin_tone:欢迎您! 该存储库是Immutable.js不可变数据收集库迷你课程的... 克隆并运行此项目: git clone https://github.com/Lectrum/immutable-js.gi
语言:English 将不可变JS对象记录到控制台时,使其更具...基于Immutable DevTools:https://github.com/andrewdavey/immutable-devtools源代码:https://github.com/mattzeunert/immutable-object-formatter-extension
前端开源库-immutable-core不变的核心,不变的模块化框架
前端开源库-immutable-ai不可变人工智能,不可变核心的可选接口
前端开源库-immutable-instance-id不可变实例ID,每个进程实例生成一次随机唯一ID
npm install immutable-object-methods --save用法import { getIn , setIn , mergeDeep , assign , set , without , chain } from 'immutable-object-methods' ;const input = { a : { b : 'c' } } ;const updated ...
python库。 资源全名:immutable_collection-1.1.post2-py2.7.egg
记录自己学习《图解Java多线程设计模式》这本书的全部过程 本书上传的所有代码都是可以运行的,在此附上本书源码地址: 在此向本书作者和译者表示感谢 运行环境 Eclipse版本:Oxygen.2 Release (4.7.2) JDK版本:jdk...
dot-prop-immutable, 点prop的不可变版本,带有一些扩展名 dot-prop-immutable 点prop的不可变版本,带有一些扩展名。npm install dot-prop-immutable这个模块的动机是在不改变普通JavaScript对象的现有状态的情况
IMMUTABLE-XJC是一个JAXB 2.x XJC插件,用于使模式派生类不可变: 删除所有的setter方法 分数班决赛 创建一个以所有字段为参数的公共构造函数 创建一个受保护的无参数构造函数 将课程中的所有字段标记为final ...
使用 npm 或 jspm 安装immutable-angular npm install immutable-angular jspm install npm:immutable-angular 包含'immutable'模块作为模块的依赖项 import 'immutable-angular' ; angular . module ( '...
java多线程设计immutable实例源码,多线程读写防止非安全问题
go-immutable-radix, 在Golang中,一个不可变的基数树实现 go-immutable-radix 提供实现不可变 radix的iradix 包。 包只提供单个 Tree 实现,针对稀疏节点优化。作为一个基数树,它提供以下内容:O(k) 操作。在许多...
article-json-immutable-methods 文章json的不可变方法安装如果尚未下载node,请从下载并安装。 npm install article-json-immutable-methods --save测验npm installnpm test依存关系 :通常可变数组方法的不可变...
immutable - Javascript不可变的持久化数据集合
单线程程序 多线程程序 Thread类的run方法和start方法 线程的启动 线程的启动(1)——利用Thread类的子类 线程的启动(2)——利用Runnable接口 线程的暂时停止 线程的共享互斥 synchronized方法 synchronized阻挡 ...