posts - 11, comments - 10, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

Effective Java读书笔记

Posted on 2006-06-29 11:32 繁星满空 阅读(1018) 评论(0)  编辑  收藏 所属分类: Java

作者简介:Joshua BlochGoogle的首席工程师,之前是Sun的杰出工程师,他领导了大量的java平台设计和实现工作,包括jdk5.0的语言增强和集合框架,拥有卡内基.梅隆大学的计算机科学的博士学位。

 

本书的目标是帮助你最有效的运用java编程语言及其基本库,java.langjava.utiljava.io。本书由57个条目组成,每个条目传达一个原则,这些原则是最有经验的程序员在实践过程中的一些有用的做法。

Creating and Destroying Object

 

Item 1: 考虑用静态工厂方法替代构造器

public static Boolean valueOf(boolean b) {

    return (b?Boolean.TRUE:Boolean.FALSE);

}

考虑在构造函数之外提供staticfactory mothod

优点:1.名字可不与类名相同,可以采用更易理解的名称。2.不必每次都返回一个新的对象。3.可以返回子类型。

缺点:1.无法被继承。2.和其它static方法无法区分。

 

Item 2: 通过添加私有构造器来加强单例属性(singletom property)

public class Hello {

public static final Hello Instance = new Hell();

    private Hello() {}                                       

}

public class Hello {

private static final Hello Instance = new Hell();

    private Hello(){}

    public static Hello getInstance() {

        return Instance;

    }

}

第二种方法可以方便改变。

如果想让singleton类成为serializable,除了implements Serializable外,还要提供readResolve()方法返回该单例。

 

Item 3: 为构造器添加private以避免被实例化

对于只是由static属性和方法构成的工具类,要为构造器添加private,以免被实例化,而不添加的话,则可能有默认的构造器。

 

 

Item 4: 避免创建重复的对象

尤其是创建比较昂贵的。

对不可修改的对象尽量进行复用,这样效率和性能都会提高。例如如果循环100String s = new String("hello")将创建100个对象 循环100String s = "hello";则只创建了一个对象。很好的进行了复用。

 

Item 5: 消除绝对的对象引用

内存泄漏,在cache里易发生。

public Object pop(){

if(size == 0) {}  

    return elements[size--];

}

public Object pop() {

if(size == 0) {}

    Object obj = elements[--size];

    elements[size] = null; 

    return obj;

}

但是不要滥用,不要每个对象使用后都用NULL

 

Item 6: 避免finalizer

不要当作C++中的析构函数,正确的方法是放在finally中。

 

 

Methods Common to All Objects

 

Item 7: 当你覆盖equals方法的时候一定要遵守general contact

覆盖equals的时候一定要加倍的小心,其实最好的办法就是不覆盖这个方法。比如在下面的情况下就可以不覆盖

   1 这个类的每个实例都是唯一的,例如Thread

   2 如果你不关心这个类是否该提供一个测试逻辑相等的方法

   3 超类已经覆盖了equals方法,并且它合适子类使用

   4 如果这个类是private或者是package-private的,并且你确信他不会被调用

覆盖时遵守的原则是

必须与自身相等,对称性A<->B,传递性,一致性如果不改变始终都是一致的结果,不能与NULL相等。

 

Item 8: 当你覆盖equals的时候必须覆盖hashCode方法

不这么做的话,有关hash-based的集合操作会出错。

契约:

同一对象的hashCode返回相同的结果(equals比较属性没改变),如果equals相等,则hashCode相等,如果equals不等,则hashCode不必不等。

 

 

Item 9: 总是覆盖toString方法

Object toString方法返回的形式是Class的类型加上@加上16进制的hashcode,不利于描述对象的信息。

 

Item 10: 谨慎覆盖clone()方法

尽量不要实现,碰到deepcopy的问题。

 

Item 11: 考虑实现覆盖Comparable接口

 

契约:传递性,x.compareTo(y)>0,y.compareTo(z)>0,x.compareTo(z)>0

如果x.compareTo(y)0,则x.compareTo(z)y.compareTo(z)结果一致

建议x.compareTo(y)0 x.equals(y)=true,但不要求。

 

 

Classes and Interfaces

 

Item 12: 把类和成员的可访问范围降到最低

通常public类里不应该有public字段,除了常量,要注意常量应该是不可修改的。

public class Con {

public static final int[] data = {1,2,3};// it is bad

public static final String hello = "world";

public static final int i = 1;

}

 

Item 13: 偏爱不可修改的类

5 个原则保证不可修改

不提供可修改对象的方法,方法不可被覆盖(final),所有字段是final,所有字段是private,确保外部不能访问到类的可修改的组件

好处

可自由共享,线程安全

 

Item 14: 优先考虑合成(复合),其次是继承

利用wrapper class,除非确实是is a的关系。

 

 

Item 15: 如果要用继承那么设计以及文档都要有质量保证,否则就不要用继承

为了避免继承带来的问题,你必须提供精确的文档来说明覆盖相关方法可能出现的问题。

在构造器内千万不要调用可以被覆盖的方法

由于在Clone()或者序列化的时候非常类似构造器的功能,因此readObject()clone()方法内最好也不要包括能被覆盖的方法。

 

 

Item 16: 使用接口代替抽象类

单重继承

 

Item 17: 接口只应该用来定义类型

常量不应该放在接口中。

 

Item 18: 优先考虑静态内部类,而非非静态内部类

 

 

Substitutes for C Constructs

 

Item 19: 用类代替结构

 

Item 20: 用类继承来代替联合

 

Item 21: 用类来代替enum结构

 

Item 22: 用类和接口来代替函数指针

 

 

Methods

 

Item 23: 检查参数的有效性

 

Item 24: 需要时使用保护性拷贝

 

Item 25: 谨慎设计方法的签名

命名,不要过分提供便利的方法,避免过长参数列表

 

对于参数类型,优先使用接口而不是类

谨慎的使用函数对象

 

Item 26: 谨慎的使用重载

 

Item 27: 返回零长度的数组而不是null

 

Item 28: 为所有导出的API元素编写文档注释

当代码能很好的说明问题时,可不写注释

 

 

General Programming

 

Item 29: 将局部变量的作用域最小化

不易阅读,在变量声明的时候初始化,try-catch例外

for 循环优于while循环,for完全独立,重用变量名不会有任何问题

for (int i=0,n=list.size(); i<n; i++) {

    dosomething(list.get(i));

}

 

Item 30: 了解和使用库

 

Item 31: 如果想要知道精确的答案,就要避免使用doublefloat

使用int,longBigDecimal

 

Item 32: 如果其他类型更适合,则尽量避免使用字符串

如枚举

 

Item 33: 了解字符串的连接功能

使用StringBuffer代替String

 

Item 34: 通过接口引用对象

参数、返回值,将会给函数带来很大的灵活

 

Item 35: 接口优先于反射机制

损失了编译期的类型检查的好处,性能上也会受损。

 

Item 36: 谨慎的使用本地方法

 

Item 37: 谨慎使用优化

不要因为性能而牺牲合理的代码结构

 

Item 38: 遵守普遍接受的命名惯例

 

 

Exceptions

 

Item 39: 仅在异常情况下使用异常

try {

int i=0;

while (true)

a[i++].f();

} catch (ArrayIndexOutOfBoundsException) {}

利用异常终止循环,不要这样滥用异常。

一个良好的设计不应该依靠异常去控制流程

 

Item 40: 可恢复状态使用检查异常(Exception),对编程错误使用运行期异常(RuntimeException)

 

Item 41: 避免不必要的使用检查异常

可以先检查是否有异常情况,而不是直接用try-catch控制程序流程

 

Item 42: 尽量使用标准异常

IllegalArgumentException 参数不合法,IllegalStateException状态不合法

NullPointerException 空指针,IndexOutOfBoundsException越界

 

Item 43: 引发的异常要与抽象对应

异常的分层,lower-level high-level

 

Item 44: 提供每个方法所抛出的异常的文档

javadoc@throws标签

一般针对检查异常

 

Item 45: messages中记录失败捕获的信息

 

Item 46: 使失败原子化

即使方法调用失败后,也要恢复对象的状态成为调用方法前的状态

 

Item 47: 不要忽略异常

不要catch块内什么都不做

 

 

Threads

 

Item 48: 同步访问共享可变的数据

private static int nextSerialNumber = 0;

// 需要同步

public static int generateSerialNumber() {

     return nextSerialNumber++;

}

public class StoppableThread extends Thread {

     private boolean stopRequested = false;

     public void run() {

         boolean done = false;

         while (!stopRequested() && !done) {

              //dosth

         }

     }

     // 需要同步

     public synchronized void requestStop() {

         stopRequested = true;

     }

     private synchronized boolean stopRequested() {

         return stopRequested;

     }

}

 

Item 49: 避免过度使用同步

性能的下降

在同步块里尽可能少的操作

 

Item 50: 不要在循环外部调用wait

一般习惯的方法

synchronized (obj) {

     while (<condition does not hold>)

         obj.wait();

     //Perform action appropriate to condition

}

 

Item 51: 不要依赖线程调度器

 

Item 52: 文档化线程安全

如果一个类支持线程安全的话,一定要文档说明

 

Item 53: 避免使用线程组

 

 

Serialization

 

Item 54: 谨慎实现Serializable

表面简单implements Serializable,实际上复杂

如果实现了,那私有或包私有的属性也会成为exported API的一部分,违背了隐藏内部实施细节的原则。

serialVersionUID 属性,如果代码中不指定的话,系统会根据类名,实现接口名,成员名称,生成一个

即使添加一个很普通的方法,也会改变该值,这样就失去兼容性。

 

Item 55: 考虑使用自定义的序列化格式

覆盖writeObject()readObject()

 

Item 56: 保护性地编写readObject方法

存在安全漏洞,反序列化

 

Item 57: 必要时提供readResolve方法


只有注册用户登录后才能发表评论。


网站导航: