概念:

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

优点

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. java8 获取对象中满足条件的金额之和

    记录一个小笔记:获取一个对象中,支付成功的金额之和: Long sum = list.stream().filter(o -> o.getStatus() == SUCCESS).mapToLo ...

  3. Build RPM package from source code

    # yum install rpm-build# wget http://rsync.samba.org/ftp/rsync/rsync-3.0.9.tar.gz# vim rsync.specNam ...

  4. 转:Java NIO(2)

    java.nio包是Java在1.4之后增加的,用来提高I/O操作的效率.在nio包中主要包括以下几个类或接口: * Buffer:缓冲区,用来临时存放输入或输出数据. * Charset:用来把Un ...

  5. 输出读入优化——QAQ

    #include<bits/stdc++.h> const int RN=1e5; ],*ip=ib+RN,ob[RN+],*op=ob; inline int gc(){ ip==ib+ ...

  6. 【IDEA】IDEA集成Tomcat7插件运行项目

    Maven已经是Java的项目管理标配,如何在JavaEE开发使用Maven调用Web应用,是很多同学关心的问题.本文将介绍,Maven如何介绍Tomcat插件. Maven Tomcat插件现在主要 ...

  7. (计数器)NOIP模拟赛(神奇的数位DP题。。)

    没有原题传送门.. 手打原题QAQ [问题描述]     一本书的页数为N,页码从1开始编起,请你求出全部页码中,用了多少个0,1,2,…,9.其中—个页码不含多余的0,如N=1234时第5页不是00 ...

  8. UVALive 3507:Keep the Customer Satisfied(贪心 Grade C)

    VJ题目链接 题意: 知道n(n <= 8e6)个工作的完成所需时间q和截止时间d,你一次只能做一个工作.问最多能做多少工作? 思路: 首先很像贪心.观察发现如下两个贪心性质: 1)一定存在一个 ...

  9. Java微信公众平台开发_01_本地服务器映射外网

    做微信开发之前,我们需要先做一个内网穿透,让我们的工程可以在公网上被访问. 一.工具列表 内网穿透的相关工具有: (1)natapp 官网 :https://natapp.cn/ (2)花生壳 官网: ...

  10. git回溯到指定版本

    git回溯到指定版本 git log命令查看仓库日志 然后使用git checkout 命令 例如回溯到上图中的版本 git checkout 12db5d6fd138922a8aaf2214c84c ...