Java 代码风格建议(翻译Google的)

本建议来自google

http://google-styleguide.googlecode.com/svn/trunk/javaguide.html

国内可能无法访问这个链接,写这篇文章的时候是在美国上的这个网络,下面的文章基本上翻译得到。

一、介绍

1.1 术语说明

在下面文档中,除非特殊说明

1. class的意思包括,普通的类,接口,枚举以及注解

2. comment 通常指implementation 的注释,没有使用短语"documentation comments" ,而是使用"Javadoc."

1.2 参考说明

文档中的实例代码是不规范的,因为如果全部是符合规范风格的代码没法举例做比较。

二、代码源文件基本风格

2.1 文件名

文件名包含了一个区分大小写的名字加上.java 的后缀

2.2 文件编码

文件编码为UTF-8

2.3 特殊字符

2.3.1 空白符

除了换行符,所有的空白的地方应该都是空格符ASCII 为(0x20),包括如下内容

1.所有其他的空白字符和是空白的字面的字都应该避免

2. Tab键产生的空格需要避免(Eclipse 有这方面的设置)

2.3.2 特殊的转义字符

对于任何有特殊的转义字符的,使用这些(\b, \t , \n , \f , \r , \", \' 和 \\),比使用效果相同的八进制(例如 \012)和Unicode(\u000a)要好。

2.3.3 Non-ASCII 码

对于一些不常用的非ASCII码,比如无穷,能避免的避免,不能的应该加上相应的注释

举个例子:

String unitAbbrev = "μs";
String unitAbbrev = "\u03bcs"; // "μs"
String unitAbbrev = "\u03bcs"; // Greek letter mu, "s"
String unitAbbrev = "\u03bcs";

 说明:

第一种最好,清楚明白,不要注释

第二种也可以,但是没有理由这么做,因为注释上能写出来,直接写出来不就行了

第三种也可以,但是比较奇怪而且容易出错

三、源代码结构风格

3.1 License 或者Copyright

如果license 或者copyright 信息属于某个文件,它应该出现在文件中

3.2 Package 的声明

包的声明不应该是大于一行的,字符数控制在一行(大概80-100,后面会说一行的字符数)

3.3  Import 的声明

3.3.1 不应该有通配符

这就说明了,如果没有特殊情况,别用xxx.*导入一个包下的所有文件的情况

3.3.2 不应该有换行符

3.3.3 排序和空白

导入的东西应该分组,不同的组用一个空白行来分开,这些组的顺序是这样的

1. 所有你自己的类在一个单独的组

2. com.google在一个组中(广告,哈哈)

3. 第三方的包,也需要按产品来分,比如android,com,junt,org,sun

4. java 的导入

5. javax的导入

3.4 类的声明

3.4.1 精确的命名最高级别的类名(类中可能有内部类)

3.4.2 类的成员排序

类成员的排序应该对学习和理解有帮助,这个没有一个秘方告诉你怎么做,不同的类成员的顺序也是不一样的。

其中一个重要的方法是按照某些逻辑规则来排序。

3.4.2.1 重载的方法永远不应该分开

四、格式化

4.1 括号

4.1.1 但有选择的情况下应该用括号

比如说存在if, else , for , do 和 while的使用,甚至内容为空。

4.1.2 非空代码块

括号参照K&R样式:

1. 括号开始(前括号)之前不要有空白行

2. 括号开始(前括号)之后要有空白行

3. 括号结束(后括号)之前应该有空白行

4. 括号结束(后括号)之后有空白行,但是如果后面接else ,catch,或者是类,结构体的的后括号,后者后面需要带分号.

下面是举例

return new MyClass() {
  @Override public void method() {
    if (condition()) {
      try {
        something();
      } catch (ProblemException e) {
        recover();
      }
    }
  }
};

4.1.3 空的块

类似空的块这样的括号应该紧跟在一起,除非是后面有多层的情况(if/else if/else 或者try/catch/finaly)

  void doNothing() {}

4.2 块缩排

不同级别的块的缩小排放是2个空白符,即2个英文字符的宽度,左右方向键应该是4个空。

4.3 一个类型的代码清单要空一行

4.4 行长度为80或者100

例外,有些情况下有例外

1.比如长的URL,JSNI的方法

2. package 或者import ,我们可以控制自己,但是控制不了别人

3. 命令行中命令,和说明,你准备把这些东西放拷贝到一个shell中的,不要因为这些规则让你很不方便。

4.5 行的折叠(Line-warpping)

通常情况下行长度为80-100,但是不要因为这个规则而让一个单词变成多个。还有有些情况下需要折叠。

4.5.1 在什么地方打断当前行

主要方向是在高语法级别处选择换行

1.比如说在多个catch的时候,多个.(点)的时候,或者继承

2. 多个定义的逗号

4.5.2 独立的连续的行被打断后,至少前面放4个空格符

4.6 空白区域

4.6.3 水平对齐:没有要求

private int x; // this is fine
private Color color; // this too

private int   x;      // permitted, but future edits
private Color color;  // may leave it unaligned

 在本文中,没有必要把所有的注释水平对齐

4.7 Grouping parentheses

4.8 特殊结构

4.8.1 枚举类型

private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }

4.8.2 变量声明

4.8.2.1 一次声明一个变量

4.8.2.2 声明之后尽快初始化

4.8.3 数组

数组的初始化,和一个块的格式是一样的,所以下面的格式都是可以的

new int[] {           new int[] {
  0, 1, 2, 3            0,
}                       1,
                        2,
new int[] {             3,
  0, 1,               }
  2, 3
}                     new int[]
                          {0, 1, 2, 3}

4.8.4 Switch

switch (input) {
  case 1:
  case 2:
    prepareOneOrTwo();
    // fall through
  case 3:
    handleOneTwoOrThree();
    break;
  default:
    handleLargeNumber(input);
}

4.8.5 注解

@Override
@Nullable
public String getNameIfPresent() { ... }
@Override public int hashCode() { ... }
@Partial @Mock DataLoader loader;

4.8.6 注释

/*
 * This is          // And so           /* Or you can
 * okay.            // is this.          * even do this. */
 */

4.8.7 修改

类和成员的修改,按照下面的推荐的顺序修改。

public protected private abstract static final transient volatile synchronized native strictfp

4.8.8 数字

Long 型的数字后缀加L比小l好

5 命名

5.1 对于所有标识符的一般规则

标识符只使用ASCII码和数字,除了下面有两种特殊情况下还会用到下划线,像下面的标识符 name_, mName, s_name, kName都不再使用。

5.2 标识符类型推荐规则

5.2.1 包名

报名全部小写,也不用下划线

例如

com.example.deepspace //推荐使用
com.example.deepSpace //不推荐使用
com.example.deep_space //不推荐使用
 5.2.2 类名

类名使用(UpperCamelCase)大骆驼拼写法。就是首字母大写的驼峰命名法。

类名通常是名词或者名词短语,如List ,但是有时候也会出现形容词或者形容词短语,如Readable。

作为测试的类通常以Test结尾,如HashTest或者HashIntegrationTest。

5.2.3 方法名

方法名用(LowerCamelCase)小骆驼拼写法。就是首字母小写的驼峰命名法。

方法名通常为动词或者动词短语,如stop

作为测试的方法通常以下划线分开名字部分,如TestPop_emptyStack。

5.2.4 常量

常量通常如下处理:名称全部大写,单词之间以下划线区分。

接下来的问题是那部分内容输入常量呢?常量应该是static final 的,但是static final的也不一定是常量,考虑到依据是这个定义是不是永远不变的。

如下例子

// Constants
static final int NUMBER = 5;
static final ImmutableList<String> NAMES = ImmutableList.of("Ed", "Ann");
static final Joiner COMMA_JOINER = Joiner.on(',');  // because Joiner is immutable
static final SomeMutableType[] EMPTY_ARRAY = {};
enum SomeEnum { ENUM_CONSTANT }  //枚举的类型是永远不变的,所以枚举里的内容应该算常量。

// Not constants
static String nonFinal = "non-final";
final String nonStatic = "non-static";
static final Set<String> mutableCollection = new HashSet<String>();
static final ImmutableSet<SomeMutableType> mutableElements = ImmutableSet.of(mutable);
static final Logger logger = Logger.getLogger(MyClass.getName());
static final String[] nonEmptyArray = {"these", "can", "change"};
  5.2.5 非常量属性命名

非常量命名应该用小驼峰命名法。名字通常也为名词或者名词短语。

5.2.6 参数命名

参数命名规则是小驼峰命名,单个字符的名字应该避免。

5.2.7 局部变量命名

书写方式为小驼峰命名法,与其它类型的变量相比是可以相对缩减单词的长度。

然而单字符的名字还是应该避免,除非是临时的或者在循环中的变量。

即使这个变量不会改变,也不应该定义一个局部变量为常量。

5.2.8 类型变量命名

有如下两种情况

1. 单个大写字符,或者后面接个单独的数字如,(E, T, X ,T2)

2. 作为一种类型的类型名,通常为类型后面加单个大写字母,如(RequestT, FooBarT)

5.3 驼峰命名定义

有的时候可以有多个方法来将一个英语的短语转换成驼峰命名式的名字,比如说IPv6, iOS之类的。

举例

分散的词组 正确的命名 不正确的
"XML HTTP request" XmlHttpRequest XMLHTTPRequest
"new customer ID" newCustomerId newCustomerID
"inner stopwatch" innerStopwatch innerStopWatch
"supports IPv6 on iOS?" supportsIpv6OnIos supportsIPv6OnIOS
"YouTube importer" YouTubeImporter
YoutubeImporter(不推荐)
 

 六 编程实践

6.1 @Override 应该总被使用

特殊情况,@Override 应该隐藏当父类的方法已经是@Deprecated

6.2 出现的异常不应该被忽略

通常异常出现了,几乎不会做任何事情。通常情况下会记录到日志中,如果认为这个异常是不可能的,重新抛出一个AssertionError.

当一个异常出现并且真的不会做任何事情,也不会有什么影响,那么一个可取的方法是在异常中加一点注释

try {
  int i = Integer.parseInt(response);
  return handleNumericResponse(i);
} catch (NumberFormatException ok) {
  // it's not numeric; that's fine, just continue
}
return handleTextResponse(response);

 还有一种特殊的情况是当作测试的时候,一个被期望出现的异常是不需要做处理和说明的。

try {
  emptyStack.pop();
  fail();
} catch (NoSuchElementException expected) {
}

6.3 静态成员,应该直接用类调用

Foo aFoo = ...;
Foo.aStaticMethod(); // good
aFoo.aStaticMethod(); // bad
somethingThatYieldsAFoo().aStaticMethod(); // very bad

七. Javadoc

7.1 格式

7.1.1 通常情况

通常情况下是下面格式

/**
 * Multiple lines of Javadoc text are written here,
 * wrapped normally...
 */
public int method(String p1) { ... }

 还有一行的情况

/** An especially short bit of Javadoc. */

7.1.2 段落

空行至出现在注释的开头,每个段落用<p>来区分,<p>后面没有空格

7.1.3 子句

标准的子句按照如下排序@parm, @return,@throws,@deprecated ,这四种类型除非没有,否则描述永远不应该为空,当这些子句不够一行的时候,下一行要四个或者以上的空格。

7.2 程序片段概要

每个类或者成员都要以一个概要描述开始,这些概要很重要,它是一定上下文中仅有的文本。

这个概要是一个名字或者动词短语,通常不是一个复杂的句子,不要以A ({@code Foo} is a ... 或者This method returns ...开头,也不是命令式的句子像Save the record.但是如果这个描述很复杂,请加上标点。

7.3 Javadoc 在哪里使用

至少要为每个public 和protected的成员加上说明,而且要说明下异常的情况。

其它类或者成员如果需要也应该加上说明。

7.3.1 例外:意义明确的方法不需要加

意义很明确的方法或者属性就不需要加说明了,直接可以通过名字看出来的像getFoo.为你的方法加上一个合适的说明是很重要的,比如说方法getCanonicalName,如果只写/**Returns the canonical name.*/就没有必要了,但是解释下CanonicalName 可能更好一些。

7.3.2 例外,重载父类的方法不总需要加上说明

猜你喜欢

转载自tangmingjie2009.iteye.com/blog/2121984