GoogleStyle

Google Java 编程风格指南

  • 1.1 术语说明
    • 1.术语class 可表示一个表示一个普通类,枚举类,接口或是annotation类型
      (@interface)
    • 2.术语comment只用来指代实现的注释(implementation comments),我们不使用“documentation
      comments”一词,而是用Javadoc。
  • 1.2 指南说

  • 2.1

    • 注意大小写,文件扩展名为 .java
  • 2.2 文件编码格式:UTF-8
  • 3.1 许可认证或版权信
    • 如果一个文件包含许可证或版权信息,则应该把它放在文件最前面。
  • 3.2 package语句不换行。
  • 3.3 import
    • 1.import不要使用通配符:
      不要出现这样的代码: ‘import java.Util.*;’
    • 2.import语句不换行。
    • 3.顺序和间距
      import语句可以分为一下几组,按照这个顺序,每组由一个空行分隔:
      * 1.所有的静态导入为独立成组
      * 2.com.google imports(仅当这个源文件是在com.google 包下)
      * 3.第三方的包。每个顶级包为一组,字典序。例如:android,com,junit,org,sun
      * 4.java imports
      * 5.javax imports
      *** 
      * 组内不空行,按字典序排列。
      
  • 3.4 类声明
    • 1.只有一个顶级类声明
      每个顶级类都在一个与它同名的源文件中
    • 2.类成员顺序
      类的成员顺序对易学性有很大的影响,但这也不存在唯一的通用法则。不同的类对成员的排序可能是不同的。
      最重要的一点,每个类应该以某种逻辑去排序它的成员,维护者应该要能解释这种排序逻辑。比如,
      新的方法不能总是习惯性地添加到类的结尾,因为这样就是按时间顺序而非某种逻辑来排序的。
      • 重载:永不分离
        当一个类有多个构造函数,或是多个同名方法,这些函数/方法应该按顺序出现在一起,中间不要放进其它的函数/方法。

格式


  • 4.1大括号
    • 使用大括号,即使时可选的
    • 非空块:K & R 风格
      对于非空格和块状结构,大括号遵循Kernighan和Ritchie风格
      • 左大括号前不换行
      • 左大括号后换行
      • 右大括号前换行
      • 如果右大括号是一个语句、函数体或是类的终止,则右大括号后需要换行,否则不换行。
    • 空块:可以用简洁版本
      一个空的块状结构里什莫也不包含,大括号可以简洁的写成{} ,不需要换行。
  • 4.2块缩进:2个空格
    每当开始一个新的块时,缩进增加2个空格,当块结束时,缩进返回先前的缩进级别,缩进级别适用于代码和注释。
  • 4.3一行一个语句
  • 4.4列限制:80或100
    一个项目可以选择一行80个字符或100个字符的列限制,超过这个字符数限制,必须自动换行。
    例外:
    • 不可能满足列限制的行(长的url)
    • package 和 import语句
    • 注释里那些可能被剪切并剪切到shell中的命令行。
  • 4.5自动换行
    • 从哪里断开
      自动换行的基本准则是:更倾向于在更高的语法处断开。
      • 如果在非赋值运算符处断开,那么在该符号前断开(比如+,它将位于下一行)。
        注意:这一点与Google其它语言的编程风格不同(如C++和JavaScript)。
        这条规则也适用于以下“类运算符”符号:点分隔符(.),
        类型界限中的&(),catch块中的管道符号(catch (FooException | BarException e).
      • 如果在赋值运算符处断开,通常的做法是在该符号后断开(比如=,它与前面的内容留在同一行)。这条规则也适用于foreach 语句中的分号。
      • 方法名或构造函数名与左括号留在同一行。
      • 逗号(,)与其前面的内容留在同一行。
    • 自动换行时缩进至少4个空格
  • 4.6 空白
    • 垂直空白
    • 水平空白
    • 对齐方式:不做要求
  • 4.7 用小括号来限定组
  • 4.8 具体结构
    • 枚举类
      枚举常量间用逗号隔开,换行可选。
      没有方法和文档的枚举类可写成数组初始化格式:
      ‘private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }’
      由于枚举类也是一个类,因此所有适用于其他类的规则同样也适用于枚举类。
    • 变量声明、
      • 每次只声明一个变量
        不要使用组合声明,比如:int a, b;.
      • 需要时才声明,并尽快进行初始化
        不要在一个代码的开始就把局部变量一次性声明,而是在第一次需要它的时候才声明,
        局部变量在声明时最好尽快完成初始化
    • 数组
      • 数组的初始化
        可写成块状结构
      • 非C语言的数组声明
        中括号是类型的一部分:String[] args ;而不是String args[];
    • switch语句
      • 缩进
        缩进2个空格
        每个switch标签新起一行,再缩进2个空格,写下一条或多条语句。
      • Fall-through:注释
        每一次switch块内,要么通过 ‘ break, continue, return ‘ 或抛出异常来终止,要么通过一条注释来说明
        程序将继续执行到下一个语句,典型的是: ‘ // fall through ’ .
      • default 的情况要写出来
    • 注释(Annotations)
      注解应放在文档块的后面,应用于类,方法,和构造函数,一个注解占据一行
      ‘ @Override
      @Nullable
      public String getNameIfPresent () { … }

      参数和局部变量注解没有特定规则。
    • 注释
    • 块注释风格
      块注释与其周围的代码在同一缩进级别。它们可以是 ‘// ‘ 风格,也可以是 ‘//…’ 风格
      对于多行注释 ‘ // ‘ 后续行必须以 ‘*’ 开始.
      段落风格的注释
    • Modifiers
      类和成员的modifiers如果存在,则按照Java语言的规范中推荐的顺序出现。
      ‘ public protected private abstract static final transient volatile native stricttfp ‘

命名约定


  • 5.1 对所有标识符都通用的规则
    标识符只能使用ASCII字母和数字,因此每个有效的标识符名称都能匹配正则表达式\w+。
    其它编程语言风格中使用的特殊前缀或后缀,如name_, mName, s_name和kName,在Java里面都不能用。
    
  • 5.2 标识符类型的规则

    • 包名
      包名全部小写,连续的单词只是简单的连接起来,不使用下划线。
    • 类名
      全部以ClassNamePeople编写。
      测试类的命名要用它要测试的类的名称开始,以 Test 结束,如HashTest
    • 方法名
      方法名都以lowerCamelCase风格编写.
    • 常量名
      常量名命名模式为CONSTANT_CASE,全部需要大写,用下划线分隔单词。
      每一个常量都是一个静态的final 字段,但不是所有的静态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"};
      
这些名字通常是名词或名词短语。
  • 非常量字段名
    非常量字段名以lowerCamelCase风格编写。
  • 参数名
    参数名以lowerCamelCase风格
  • 局部变量名
    局部变量名以lowerCameCase风格编写,避免使用单字节进行命名,除里临时变量和循环变量。
  • 类型变量名
    • 单个大写字母,后面可以跟一个数字。(E, T, T2)
    • 以类命名方式,后面加个大写的T
    • 5.3 驼峰式命名法。

编程实践


  • 6.1 @Override:能用则用
    只要是合法的,就用上。
  • 6.2 捕获的异常:不能忽视
    典型的相应方式是打印日志
    try catch 除外:
    不需要在catch里面中添加任何代码,需要注释加以说明
    try {
          int i = Integer.parseInt(response);
          return handleNumericResponse(i);
      } catch (NumberFormatException ok) {
          // it's not numeric; this's fine, just continue
      }
      return handleTextResponse(response);
    
    如果一个捕获的异常被命名为excepted,则它不需要加注释的忽略,可以直接或略。
    try {
      emptyStack.pop();
      fail();
    } catch (NoSuchElementException excepted) {
    }
    
  • 6.3 静态成员:使用类名进行调用

使用类名调用静态的类成员,而不是具体某个对象或表达式。
充分利用静态成员的优势。

  • 6.4 Finalizers:禁用
    极少会去重载Object.finalize .

    Tip : 不要使用finalize 。

Javadoc


  • 7.1 格式

    • 一般格式
      /**

      • Multiple lines of Javadoc text are written here,
      • wrapped normally…
        /
        public int method(String p) { … }
        或者是单行模式:
        /** todo
        /
    • 段落
      空行

    • javadoc 标记
      标准的Javadoc标记按以下顺序出现:@param, @return, @throws, @deprecated,
      前面这4种标记如果出现,描述都不能为空。
  • 7.2 摘要片段
    每个类或成员的Javadoc以一个简短的摘要片段开始。这个片段是非常重要的,在某些情况下,它是唯一出现的文本,比如在类 和方法索引中。
  • 7.3 哪里需要使用Javadoc
    至少在每个public类及它的每个public和protected成员处使用Javadoc,以下是一些例外:
    • 例外:不言自明的方法
      get set 方法。
    • 例外:重载
      如果一个方法重载了超类中的方法,那么Javadoc并非必需的。
    • 可选的Javadoc
      对于包外不可见的类和方法,如有需要,也是要使用Javadoc的。如果一个注释是用来定义一个类,方法,
      字段的整体目的或行为,那么这个注释应该写成Javadoc,这样更统一更友好。

Done


chenzhao@hustunique.com