EffectiveJava(15)强化对象和域的不可变性
概念:
不可变类是其实例不能被修改的类,不可变类比可变类更加易于设计 实现和使用.它们不容易出错,而且更加安全.
优点
1.不可变对象只有创建时状态.
2.不可变对象本质上是线程安全的,它们不要求同步
3.不可变对象和其内部信息可以被自由共享.这条导致的结果是不可变类永远也不需要进行任何拷贝(拷贝对象始终为原始对象).
public static final Complex ZERO = new Complex(0.0);
4.不可变对象为其他对象提供了大量构件,其他对象无论是否可变.
缺点:
它只有唯一一个缺点:对于每个不同的值都需要单独创建一个对象
改变BigInteger的低位
BigInteger moby = new BigInteger("198");
//多步骤操作,每个步骤都会创建一个对象,除了最后的结果之外,其他对象都会被抛弃
moby = moby.flipBit(0);
//它只有在需要进一的时候,才会自减一 199>198 100-198>101-199
System.out.println(moby);
运行之后我们可以看到,需要很长时间才能计算完成
针对它的性能问题(缺点)也有优化方法
1.猜测会经常使用哪些多步骤操作,然后将他们作为基本类型提供
2.提供一个公有的可变嵌套类:String的可变嵌套类为StringBuilder
不可变类创建规则:
1.不要提供任何会修改对象状态的方法
2.保证类不会被扩展:防止子类假装对象的状态已经改变而破坏该类的不可变行为
a.一般把类声明为final
b.让类的所有构造器都变成私有的或者包级私有的,并添加公有的静态工厂方法
有关于静态工厂方法,请跳转:http://blog.csdn.net/jacxuan/article/details/56849989
// public Complex(double re, double im) {
// this.re = re;
// this.im = im;
// }
// 通过让类的所有构造器变成私有或者包级私有并添加公有的静态工厂来代替公有构造器来让不可变类变为final
private Complex(double re, double im) {
this.re = re;
this.im = im;
}
public static Complex valueOf(double re, double im) {
return new Complex(re, im);
}
3.使所有域都是final的
4.使所有域都成为私有的:防止被域引用的可变对象的权限,并防止客户端直接修改这些对象.公有final域不建议
5.确保对于任何可变组件的互斥访问:如果类具有指向可变对象的域,则必须确保该类的客户端无法获得指向这些对象
的引用.并且,永远不要用客户端提供的对象引用来初始化这样的域,也不要从任何访问方法中返回该对象的引用.
6.坚决不要为每个get方法编写一个相应的set方法.
创建一个不可变的类:
这个类表示一个复数(具有实部和虚部),他除了提供标准的Object方法之外,还提供了针对实部和虚部的访问方法
,以及四种混合运算.
注意这些算法运算是如何创建并返回新的Complex实例的
public final class Complex {
public final double re;
public final double im;
public Complex(double re, double im) {
this.re = re;
this.im = im;
}
// 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 + 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));
}
@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Complex))
return false;
Complex c = (Complex) o;
// See page 43 to find out why we use compare instead of ==
// 见43页找出为什么我们使用比较而不是= =
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 im2) {
long longBits = Double.doubleToLongBits(re);
return (int) (longBits ^ (longBits >>> 32));
}
@Override
public String toString() {
return "(" + re + "+" + im + "i)";
}
}
ps:如果你正在编写一个安全性依赖于BigInteger或者BigDecimal参数的不可变性,就必须进行检查,
以确定这个参数是真正的BinInteger或BigDecimal,而不是不可信任的子类的实例.如果是后者的
话,必须假设它是可变的前提下对它进行可变性拷贝
public static BigInteger safeInstance(BigInteger val){
if(val.getClass()!=BigInteger.class)
return new BigInteger(val.toByteArray());
return val;
}
总结:如果类不能被做成不可变的,仍然应该尽可能限制它的可变性.
EffectiveJava(15)强化对象和域的不可变性的更多相关文章
- Delphi属性比对象的域有更强的功能
8.4 Delphi自定义组件(3) http://tech.163.com 2006-04-29 11:49:34 来源: 清华大学出版社 网友评论0 条 论坛 3. 测试未安装的组件 在将新组 ...
- EffectiveJava——用函数对象表示策略
有些语言支持函数指针.代理.lambda表达式,或者支持类似的机制,允许程序把“调用特殊函数的能力”储存起来并传递这种能力.这种机制通常用于允许函数的调用者通过传入第二个函数,来指定自己的行为.比较器 ...
- 《深入Java虚拟机学习笔记》- 第15章 对象和数组
1.针对对象的操作码 实例化一个新对象需要通过new操作码来实现. 对象的创建 操作码 操作数 说明 new index 在堆中创建一个新的对象,将其引用压入栈 new操作码后面紧跟一个无符号16位数 ...
- ServletContext对象--三大域对象
Servlet三大域对象的应用 request.session.application(ServletContext) ServletContext是一个全局的储存信息的空间,服务器开始就存在,服务器 ...
- java web jsp学习笔记--概述-常用语法,指令,动作元素,隐式对象,域对象
JSP学习笔记 1.什么是jsp JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术.JSP/Servlet规范.JS ...
- JSP中的9大内置对象四大域与servlet里的三大域
九大内置对象 隐式对象 说明 out 转译后对应JspWriter对象,其内部关联一个PringWriter对象 request 转译后对应HttpServletRequest/ServletRequ ...
- JSP--JSP语法--指令---九大隐式对象--四大域对象--JSP内置标签--JavaBean的动作元素--MVC三层架构
一.JSP 原理:JSP其实就是一个servlet. Servlet负责业务逻辑处理,JSP只负责显示.开发中,JSP中不能有一行JAVA代码 二.JSP语法 1. JSP模板元素:JSP中HTML标 ...
- JSP--JSP语法--指令--include(动态包含/静态包含)--九大隐式对象--四大域对象--JSP内置标签--JavaBean的动作元素--MVC三层架构
一.JSP 原理:JSP其实就是一个servlet. Servlet负责业务逻辑处理,JSP只负责显示.开发中,JSP中不能有一行JAVA代码 二.JSP语法 1. JSP模板元素:JSP中HT ...
- javaweb九大个内置对象,四大域
9个内置对象如下: 1.session对象:会话对象 当客户端第一次访问服务器的页面时,web服务器会自动为该客户端创建一个session对象并分配一个唯一的id号 常常用它来在多个页面间共享数据,如 ...
随机推荐
- RDM原始设备映射
在一个存储区域网络(SAN)上,有两种方法为虚拟机配置存储.一种方法是使用VMFS,这是VMware Infrastructure(VI)提供的专有高性能集群文件系统.对大多数企业应用来说,在VMFS ...
- float存储
浮点型变量在计算机内存中占用4字节(Byte),即32-bit.遵循IEEE-754格式标准. 一个浮点数由2部分组成:底数m 和 指数e. ±man ...
- 洛谷 P2715 约数和
给出a和b求a^b的约数和. 题目描述 输入输出格式 输入格式: 一行两个数a,b. 输出格式: 一个数表示结果对 9901 的模. 输入输出样例 输入样例#1: 2 3 输出样例#1: 15 说明 ...
- 一种机制,与js类似
我们知道,当两个条件进行逻辑与操作的时候,其中任何一个条件为假,则表达式的结果为假.所以,遇到(A 且 B)这种表达式,如果A为假的话,B是不是真假都无所谓了,当遇到一个假条件的时候,程序也就没有必要 ...
- GHC extensions
OverloadedStrings 这是最常见的一个扩展,很多时候都能看到 Haskell中,数字是num的多态,比如: a :: Int a = 1 b :: Double b = 1 ...
- 【排序算法】java实现
1.冒泡排序 最简单的排序实现,冒泡排序,是一种交换排序,它的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止. //冒泡排序 private int[] bubbleSo ...
- This Android SDK requires Android Developer Toolkit version 20.0.0 or above
本人最近在操作更新ANDROID SDK时出现类似于题目中的错误,是一启动ECLIPSE时.但是,我现在只是想恢复到原先的开发环境.于是找到本文,方法有效!!! windows 下面安装Android ...
- [BZOJ2442][Usaco2011 Open]修剪草坪 dp+单调队列优化
2442: [Usaco2011 Open]修剪草坪 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1118 Solved: 569[Submit] ...
- React Native WebView关闭缓存
React Native WebView关闭缓存 网上搜索没有找到关闭React Native下webview控件的缓存的方法,经测试找到解决方案,记录如下 核心思路:通过请求时设置请求头,使页面缓存 ...
- HDU 3466 Proud Merchants【贪心 + 01背包】
Recently, iSea went to an ancient country. For such a long time, it was the most wealthy and powerfu ...