第15条:使可变性最小化

  通过一个复数类来看不可变类。

public final class Complex {
private final double re;
private final double im; 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);
} public static Complex valueOfPolar(double r, double theta) {
return new Complex(r * Math.cos(theta), r * Math.sin(theta));
} 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 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)";
}
}

  复数类具有实部和虚部,它提供的加减乘除运算都是返回新的Complex实例,而不是修改这个实例。不可变对象有很多优点,它只有一种状态,即被创建时的状态,而且前面也提到过,它本质上是线程安全的。

  这里还用到一个小技巧,对频繁使用的值,为它们提供公有的静态final常量。

  还有一种构建不可变类的常用方法,让类的构造器私有化,并添加上公有静态工厂方法,前面也提到过。

  String类就是不可变类一个典型例子。但是细心的读者肯定会发现String类的hash属性不是final类型的,事实上,许多不可变类都拥有一个或多个非final的域,在第一次请求的时候计算出来缓存在这些域中,从而节约了计算所需要的花销。因为对象是不可变的,它的不可变性保证了计算结果相同。

public final class String{
private final char value[];
private int hash; public int hashCode() {
int h = hash;
//只有hash不存在时才去计算
if (h == 0 && value.length > 0) {
char val[] = value; for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
}

第16条:复合优先于继承

  简而言之,只有当两者确实存在is-a的关系时,才使用继承。否则,都应该使用复合。对于这一条,应用最典型的例子就是设计模式中的装饰者模式

Effective Java2读书笔记-类和接口(二)的更多相关文章

  1. Effective Java2读书笔记-类和接口(一)

    第13条:使类和成员的可访问性最小化 设计良好的模块的模块与设计不好的模块区别在于,设计良好的模块会隐藏所有的实现细节,把它的API与他的实现清晰地隔离开来.然后模块之间只通过API通信. 信息隐藏之 ...

  2. Effective Java2读书笔记-类和接口(五)

    第21条:用函数对象表示策略 这一条其实也没说啥,就是策略模式.碰到这种场景时,定义一个策略接口,然后不同策略子类实现它,主类包含这个接口的引用就可以了. 第22条:优先考虑静态成员类 嵌套类是指被定 ...

  3. Effective Java2读书笔记-类和接口(四)

    第19条:接口只用于定义类型 这一条就举了一个反例,说有些接口中只包含常量.这是对接口的不良使用.要实现相同的功能,应该使用不可实例化的工具类(第4条说过). public class Physica ...

  4. Effective Java2读书笔记-类和接口(三)

    第17条:要么为继承而设计,并提供文档说明,要么就禁止继承 第18条:接口优于抽象类 这两条中,提到了一个很重要的概念骨架实现.也就是说,抽象类实现接口的形式.这样的好处是,接口本来不能提供默认的实现 ...

  5. Effective Java读书笔记--类和接口

    1.使类和成员的可访问性最小化不指定访问级别,就是包私有.protected = 包私有 + 子类一般private不会被访问到,如果实现了Serializable,可能会泄露.反射.final集合或 ...

  6. Effective Java2读书笔记-对于所有对象都通用的方法(二)

    第10条:始终要覆盖toString 这一条没什么好讲的,就是说默认的toString方法打印出来的是类名+@+十六进制哈希码的值.我们应该覆盖它,使它能够展示出一些更为详细清晰的信息,这个看实际情况 ...

  7. Effective Java2读书笔记-创建和销毁对象(二)

    第3条:用私有构造器或者枚举类型强化Singleton属性 这一条,总体来说,就是讲了一个小技巧,将构造器声明为private,可以实现单例.具体有以下几种实现的方式. ①最传统的单例实现模式,可能有 ...

  8. 《Java核心技术》 -- 读书笔记 ② - 类 | 对象 | 接口

    对象vs对象变量 “对象” 描述的是一个类的具体实例,他被java虚拟机分配在 "堆" (Heap)中. “对象变量” 为一个对象的引用(对象变量的值=记载着具体对象的位置/地址) ...

  9. Effective Java2读书笔记-对于所有对象都通用的方法(三)

    第12条:考虑实现Comparable接口 这一条非常简单.就是说,如果类实现了Comparable接口,覆盖comparaTo方法. 就可以使用Arrays.sort(a)对数组a进行排序. 它与e ...

随机推荐

  1. MFC消息映射与命令传递

    题外话:刚开始学视窗程序设计的时候,我就打印了一本Windows消息详解,里面列举了各种已定义消息的意义和作用,共10多页,在编程的时候翻翻,有时觉得很受用.我发觉很多编程的朋友,虽然每天都面对消息, ...

  2. 转:什么是CGI、FastCGI、PHP-CGI、PHP-FPM、Spawn-FCGI?

    什么是CGI CGI全称是“公共网关接口”(Common Gateway Interface),HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上. CGI可以用 ...

  3. 8.1 Optimization Overview

    8.1 Optimization Overview 8.1 Optimization Overview 8.2 Optimizing SQL Statements 8.3 Optimization a ...

  4. 玩转指针(Playing with Pointers)

    Question: What is a Pointer? What are its limitations? What are its benefits? How do we use it? What ...

  5. Java代码编译和执行的整个过程

    Java代码编译是由Java源码编译器来完成,流程图如下所示: Java字节码的执行是由JVM执行引擎来完成,流程图如下所示: Java代码编译和执行的整个过程包含了以下三个重要的机制: Java源码 ...

  6. java_final

  7. hdu2531之BFS

    Catch him Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  8. HADOOP集群监控工具AMBARI

    HADOOP集群监控工具AMBARI安装 Apache Ambari是对Hadoop进行监控.管理和生命周期管理的开源项目.它也是一个为Hortonworks数据平台选择管理组建的项目.Ambari向 ...

  9. ViewPager实现页卡的3种方法(谷歌组件)

    ----方法一:---- 效果图: 须要的组件: ViewPager+PagerTabStrip 布局文件代码: <!--xmlns:android_custom="http://sc ...

  10. 利用iptables实现基于端口的网络流量统计

    如何统计某个应用的网络流量(包括网络流入量和网络流出量)问题,可以转换成如何基于端口号进行网络流量统计的问题.大部分网络应用程序都是传输层及以上的协议,因此基于端口号(tcp, udp)统计网络流量基 ...