概念:

不可变类是其实例不能被修改的类,不可变类比可变类更加易于设计 实现和使用.它们不容易出错,而且更加安全.

优点

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)强化对象和域的不可变性的更多相关文章

  1. Delphi属性比对象的域有更强的功能

    8.4 Delphi自定义组件(3) http://tech.163.com 2006-04-29 11:49:34 来源: 清华大学出版社 网友评论0 条 论坛   3. 测试未安装的组件 在将新组 ...

  2. EffectiveJava——用函数对象表示策略

    有些语言支持函数指针.代理.lambda表达式,或者支持类似的机制,允许程序把“调用特殊函数的能力”储存起来并传递这种能力.这种机制通常用于允许函数的调用者通过传入第二个函数,来指定自己的行为.比较器 ...

  3. 《深入Java虚拟机学习笔记》- 第15章 对象和数组

    1.针对对象的操作码 实例化一个新对象需要通过new操作码来实现. 对象的创建 操作码 操作数 说明 new index 在堆中创建一个新的对象,将其引用压入栈 new操作码后面紧跟一个无符号16位数 ...

  4. ServletContext对象--三大域对象

    Servlet三大域对象的应用 request.session.application(ServletContext) ServletContext是一个全局的储存信息的空间,服务器开始就存在,服务器 ...

  5. java web jsp学习笔记--概述-常用语法,指令,动作元素,隐式对象,域对象

     JSP学习笔记 1.什么是jsp JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术.JSP/Servlet规范.JS ...

  6. JSP中的9大内置对象四大域与servlet里的三大域

    九大内置对象 隐式对象 说明 out 转译后对应JspWriter对象,其内部关联一个PringWriter对象 request 转译后对应HttpServletRequest/ServletRequ ...

  7. JSP--JSP语法--指令---九大隐式对象--四大域对象--JSP内置标签--JavaBean的动作元素--MVC三层架构

    一.JSP 原理:JSP其实就是一个servlet. Servlet负责业务逻辑处理,JSP只负责显示.开发中,JSP中不能有一行JAVA代码 二.JSP语法 1. JSP模板元素:JSP中HTML标 ...

  8. JSP--JSP语法--指令--include(动态包含/静态包含)--九大隐式对象--四大域对象--JSP内置标签--JavaBean的动作元素--MVC三层架构

    一.JSP 原理:JSP其实就是一个servlet. Servlet负责业务逻辑处理,JSP只负责显示.开发中,JSP中不能有一行JAVA代码 二.JSP语法 1.    JSP模板元素:JSP中HT ...

  9. javaweb九大个内置对象,四大域

    9个内置对象如下: 1.session对象:会话对象 当客户端第一次访问服务器的页面时,web服务器会自动为该客户端创建一个session对象并分配一个唯一的id号 常常用它来在多个页面间共享数据,如 ...

随机推荐

  1. 使用jdk中的java.sql包中的方法进行jdbc连接

    首先说明用 java.sql包进行jdbc连接的步骤: 1.加载数据库的驱动.(一般是oracle和mysql,oracle的数据驱动名是:Oracle.jdbc.driver.OracleDrive ...

  2. maven使用nexus服务器

    1.找到maven的安装路径,例如:C:\apache-maven-3.3.9 打开conf目录下的settings.xml文件 2.在<servers>节点下,配置 <server ...

  3. mac 安装 mysql 配置

    前言:下面主要介绍2种安装方法以及后续的配置,希望对大家有帮助.(推荐通过安装包的形式安装) 1. 使用安装包安装 mysql 双击打开安装文件         双击pkg文件安装         一 ...

  4. vue jsonp解决跨域处理

    1.安装vue jsonp npm i -S vue-jsonp 2.在main.js中导入vue-jsonp import VueJsonp from 'vue-jsonp' 通过use方法,挂载到 ...

  5. Android横竖屏总结(转)

    Android横竖屏总结(转) 横竖屏切换后Activity会重新执行onCreat函数,但是在Android工程的Mainfest.xml中加入android:screenOrientation=& ...

  6. tips 前端 背景与元素的透明和模糊

    碰到好几次这样的情况了: 一个带点儿文艺效果 背景图片模糊 而一行别致的文字清晰的悬浮在背景上(口胡,加点美好的想象,生活会更美好) 第一反应是 this is easy. cause i know ...

  7. [bzoj2245][SDOI2011]工作安排——费用流

    题目大意: 传送门 题解: 很容易建模,把每一个工作人员拆成两个点,由第一个点向第二个点连S+1条边即可. 这水题没什么难度,主要是longlong卡的丧心病狂... 代码 #include < ...

  8. C#的泛型委托Predicate/Func/Action

    Predicate<T> 是一个委托,它代表了一个方法,它的定义是: namespace System {    // 摘要:    表示定义一组条件并确定指定对象是否符合这些条件的方法. ...

  9. 关于js拖拽功能,拖拽元素的position:fixed;left:0;right:0;样式引起左右拖动元素会出现落后鼠标移动距离的问题

    被拖拽元素的样式如果为:position:fixed;left:0;right:0;(当时是为了让fixed定位的元素水平居中加的left:0;right:0;避免js动态计算定位的麻烦)时左右拖动会 ...

  10. Fiddler抓包8-打断点(bpu)【转载】

    本篇转自博客:上海-悠悠 原文地址:http://www.cnblogs.com/yoyoketang/tag/fiddler/ 前言 先给大家讲一则小故事,在我们很小的时候是没有手机的,那时候跟女神 ...