文档约定

1.为那些使用你代码和维护它的人写文档

2.保持注释与代码同步

注释类型

1.使用文档注释来描述程序接口

/**
*A documentation comment
*/

2.使用标准注释来隐藏代码而不是删除

/*
*A standard comment
*/

3.使用单行注释来解释实现细节

//A one-line comment

文档注释

1.在写代码之前描述程序接口

2.对public、protected、package和private 成员进行文档注释

3.对每一个包提供概述

4.对每一个应用或者包的组提供概述,可以在package使用@see标签

注释内容

1.给每一个方法提供概述

2.完整描述每一方法签名

3.包含示例,例如:ateFormat的类的注释

/**
* ...
* If you are formatting multiple numbers, it is
* more efficient to get the format just once so
* the system does not have to fetch the
* information about the local language and
* country conventions multiple times:
* <pre>
* DateFormat df = DateFormat.getDateInstance();
* for (int i = 0; i < a.length; ++i) {
* output.println(df.format(myDate[i]) + "; ");
* }
* </pre>
* To format a number for a different Locale,
* specify the locale in the call to
* <code>getDateInstance</code>:
* <pre>
* DateFormat df;
* df = DateFormat.getDateInstance(Locale.US);
* </pre>
* ...
*/
public abstract class DateFormat extends Format {
...
}

4.对前置、后置、不变条件进行文档注释

5.对已知的缺陷和不足进行文档注释

6.对synchronized同步语法进行文档注释

内部注释

1.只有当内部注释有助于其他人理解你的代码时才添加,所以没用的注释、无关联的注释不要添加

2描述代码为什么那样做,而不是做了什么

3.避免使用行尾的注释,行尾注释只能在很短的注释时使用

4.使用行尾注释解析局部变量声明

int cur = 0; // Index of current pattern element

5.建立并使用一套关键字来标记未确定的情况

// :UNRESOLVED: EBW, 11 July 1999
// This still does not handle the case where
// the input overflows the internal buffer!!
while (everMoreInput) {
...
}

6.在两个case标签中,如果没有break语句分隔这些标签,加入”fall-through”注释

switch (command) {
  case FAST_FORWARD:
    isFastForward = true;
    // Fall through!
  case PLAY:
  case FORWARD:
    isForward = true;
    break;
  case FAST_REWIND:
    isFastRewind = true;
    // Fall through!
  case REWIND:
    isRewind = true;
  break;
  ...
}

7.在嵌套程度高的控制结构中标记结束

  for (i...) {
    for (j...) {
      while (...) {
        if (...) {
          switch (...) {
            ...
          } // end switch
        } // end if
      } // end while
    } // end for j
  } // end for i

编码约定

1.考虑将状态不变的类声明为final,如:

public final class BitSet ... {
public BitSet() {...}
public BitSet(int) {...}
public void set(int) {...}
public boolean get(int) {...}
public int size() {...}
}

2.定义更小的类和方法

3.定义子类使之可以父类使用的任何地方使用,可以使用开放-关闭原则(对扩展开放,对修改关闭)设计父类和子类

4.使所有成员变量私有

5.使用多态来替代instanceof,更安全的做法

类型安全

1.以操作java.lang.Object来包装通用类,提供静态类型检查

public class Queue {
  public void enqueue(Object object) {...};
  public Object dequeue() {...};
}
public class OrderQueue {
  private Queue queue;
  public OrderQueue()
  this.queue = new Queue();
}
  public void enqueue(Order order) {
    this.queue.enqueue(order);
  }
  public Order dequeue() {
    return (Order)this.queue.dequeue();
  }
}

2.以类的形式来封装枚举类型

表达式

1.使用相当的方法来替换重复出现的、有点复杂的表达式。分解出常见的功能,并重新包装为方法或类

2.使用块状语句来替代控制流结构的表达式

for (int i = n;i >= 0;i--) {
  for (int j = n;j >= 0;j--) {
    f(i,j);
    g(i,j); // Can add here!
  }
}

3.使用括号明确运算顺序

// Extraneous but useful parentheses.
int width = (( buffer * offset ) / pixelWidth )+ gap;

4.在switch语句最后一个case中总是键入Break语句

5.使用equals()而不是==来测试对象的相等性

构造函数

1.不要在构造函数中调用非final方法

2.使用嵌套构造函数来消除冗余代码

class Account {
  String name;
  double balance;
  final static double DEFAULT_BALANCE = 0.0d;
  Account(String name, double balance) {
    this.name = name;
    this.balance = balance;
  }
  Account(String name) {
    this(name, DEFAULT_BALANCE);
  }
}

异常处理

1.使用不需检查运行时异常来报告严重的、无法预期的错误,这可能指出程序逻辑中的错误。

2.使用需检查异常来报告可能发生但是在正常程序操作中很难发生的错误

3.使用return代码来报告期望的状态改变。

4.仅以增加信息形式来改变异常。保留所有的异常信息

try {
  for(int i = v.size();--i >= 0;) {
    ostream.println(v.elementAt(i));
  }
}catch (ArrayOutOfBounds e) {
  // should never get here
  throw new UnexpectedExceptionError(e);
}

5.不要略去运行时或错误异常

6.使用finally块以释放资源

断言

1.编程遵守约定

prepend(Object object) {
  // Test pre-condition
  if (Assert.ENABLED)
  Assert.isTrue(object != null);
  doPrepend(object);
  // Test post-condition
  if (Assert.ENABLED)
  Assert.isTrue(first() == object);
}

2.使用断言捕获代码中的逻辑错误

3.在任何一个合适的公开方法使用断言测试方法的前置和后置条件

并发

1.仅在适当时使用线程

  • 同时对多个事件作出反应

例子 ︰ 互联网浏览器或服务器。

  • 提供高水平的响应能力。

示例 ︰ 用户界面执行可以继续对用户操作做出响应,尽管应用程序的执行其他计算。

  • 如果要充分利用具有多个处理器的机器。

示例 ︰ 针对特定的计算机体系结构的应用程序。

同步

1.避免同步

2.使用同步包装来提供同步接口

public class Stack {
  public void push(Object o) {...};
  public Object pop() {...};
  public static Stack createSynchronizedStack() {
    return new SynchronizedStack();
  }
}
class SynchronizedStack extends Stack {
  public synchronized void push(Object o) {
  super.push(o);
}
public synchronized Object pop() {
  return super.pop();
  }
}

3.如果方法包含几个不需要同步的重要步骤,那么不要同步整个方法,使用同步代码块

4.当读写实例变量时避免不必要的同步

5.考虑用notify()替代notifyAll()

6.对于同步的初始化应使用双重检查模式

Log getLog() {
  if (this.log==null) {
  synchronized (this) {
    if (this.log==null) {
    this.log = new Log();
    }
  }
}
return this.log;
}

效率

1.使用延迟初始化,类的对象如果不需要马上使用就不需要马上来创建

class PersonalFinance {
  LoanRateCalculator loanCalculator = null;
  LoanRateCalculator getLoanCalculator() {
  if (this.loanCalculator == null)
    this.loanCalculator =new LoanRateCalculator();
    return this.loanCalculator;
  }
}

2.避免创建不必要的对象

3.重复初始化和重复使用对象以避免创建新的对象,可以使用工厂模式来负责对象的创建

4.留待以后优化,如果你真的需要去优化代码的时候再去做

包约定

1.把经常使用、变化和发布或者彼此互相依赖的的类放置在相同的包中

2.将volatile类和接口隔离在单独的包中

3.避免创建的包,依赖于经常变化的包,使其很难变化

4.最大的抽象化以达到最大的稳定性

5.采用高水平的设计和架构使包保持稳定

一般约定

1.保持最初的样式,不要在一个文件里使用多种风格不一的代码,会造成代码阅读困难

2.遵守最小惊奇原则

  • 简单的类和方法;
  • 代码能描述清楚类、接口、方法、变量、对象为什么要用、怎么用、在哪里用、什么时候用、互相的调用;
  • 为函数添加完整的注释;
  • 相似的类的代码看起来是相似的,不相似的类的代码看起来是不相似的;
  • 文档化的注释给用户提示可能发生的错误和异常

3.从代码编写开始就应当做好

4.任何背离约定的代码都应该文档注释

格式约定

1.善用空格或tab键,约束嵌套代码

class MyClass{
..void function(int arg){
....if(arg>0){
......for(int index=0;index<=arg;index++){
........
......}
....}
..}
}

2.拆分长行。一行一个语句,一个语句不超过一页中可阅读的最大字符数,超过就拆分为多个语句(如果可以的话),不然就以操作符为换行标识

命名约定

1.使用有意义来命名类、成员变量、方法、局部变量

2.不要使用过长的名称。缩短了名称,如果觉得不合适、不容易理解,还是使用长名称。如:

appendSignature(好)、appendSgntr(坏)

3.使用熟悉的名称,如果是消费者就使用Customer,而不要使用Client(客户)

4.只对简称的第一个字母大写,但不适用于常量命名

5.不要使用只依赖于大小写来区分的名称

包命名

1.采用你组织的Internet域名的反转、小写形式作为包名称的根限定词,如:

Internet domain name为sinobest.com,该包下为服务器发布包,所以完整的package名为com.sinobest.server

2.使用一个唯一的小写单词作为每个包的根名称,且根名称应该是有意义的缩写

3.只有当包的新版本仍然与旧版本兼容时,对于包的新版本使用相同的名称,否则使用新名称

类型命名

1.对于类和接口名称只对每个单词的第一个字母大写。

类命名

1.使用名词来命名类,如:

CustomerAccount 、KeyAdapter

接口命名

1.适应名词或形容词来命名接口,因为使用名词主要作为服务声明的描述,而使用形容词主要作为作用的描述,如: ` Runnable `

方法命名

1.方法名词中第一个单词小写,后续的每一个单词仅第一个字母大写

2.使用动词来命名方法

3.命名属性访问的目的,如:

boolean isVaild(){
  ....
  return isVaild;
}
String getName(){
  return this.name;
}

变量命名

1.变量名词中的第一个单词小写,后续的每一个单词仅第一个字母大写

2.使用名词来命名成员变量

3.对于集合引用的名称采用复数形式

4.对于通常的临时变量,建立并使用一套标准名称,如:

字符可用 c,d,e
坐标可用 x,y,z
异常可用 e
图形可用 g
对象可用 o
流可用 in,out
字符串可用 s

参数命名

1.当构造函数或者”set”方法想成员分配参数时,参数的命名应和成员相同

常量命名

1.当命名常量时,每个单词均大写,单词之间以下划线区分