阿里Java编程规约【三】代码格式

三. 代码格式

  1. 【强制】大括号的使用约定。如果是大括号内为空,则简洁地写成{}即可,不需要换行 ; 如果是非空代码块则:
      1 ) 左大括号前不换行。
      2 ) 左大括号后换行。
      3 ) 右大括号前换行。
      4 ) 右大括号后还有 else 等代码则不换行 ; 表示终止的右大括号后必须换行。

  2. 【强制】 左小括号和字符之间不出现空格 ; 同样,右小括号和字符之间也不出现空格。详见第 5 条下方正例提示。
    反例: if (空格 a == b 空格)

  3. 【强制】 if / for / while / switch / do 等保留字与括号之间都必须加空格。

switch 可以取byteshortintchar、在java1.5后支持枚举, 在java1.7后支持了对String的判断

  1. 【强制】任何二目、三目运算符的左右两边都需要加一个空格。
    说明:运算符包括赋值运算符=、逻辑运算符&&、加减乘除符号等。

  2. 【强制】采用 4 个空格缩进,禁止使用 tab 字符。
    说明:如果使用 tab 缩进,必须设置 1 个 tab 为 4 个空格。

  • IDEA 设置 tab 为 4 个空格时,请勿勾选 Use tab character ;
  • eclipse 中,必须Window-->Preferences-->General-->Editors-->Text Editors右側勾选 insert spaces for tabs 。

正例: ( 涉及 1-5 点 )

    public static void main(String[] args) {
        // 缩进 4 个空格
        String say = "hello";
        // 运算符的左右必须有一个空格
        int flag = 0;
        // 关键词 if 与括号之间必须有一个空格,括号内的 f 与左括号,0 与右括号不需要空格
        if (flag == 0) {
            System.out.println(say);
        }
        // 左大括号前加空格且不换行;左大括号后换行
        if (flag == 1) {
            System.out.println("world");
            // 右大括号前换行,右大括号后有 else,不用换行
        } else {
            System.out.println("ok");
            // 在右大括号后直接结束,则必须换行
        }
    }
  1. 【强制】注释的双斜线与注释内容之间有且仅有一个空格。
    正例: // 注释内容,注意在 // 和注释内容之间有一个空格。

  2. 【强制】单行字符数限制不超过 120 个,超出需要换行,换行时遵循如下原则:
      1) 第二行相对第一行缩进 4 个空格,从第三行开始,不再继续缩进,参考示例。
      2 ) 运算符与下文一起换行。
      3 ) 方法调用的点符号与下文一起换行。
      4 ) 方法调用时,多个参数,需要换行时,在逗号后进行。
      5 ) 在括号前不要换行,见反例。
    正例:

StringBuffer sb = new StringBuffer();
// 超过 120 个字符的情况下,换行缩进 4 个空格,点号和方法名称一起换行
sb.append("zi").append("xin")...
    .append("huang")...
    .append("huang")...
    .append("huang");

反例:

StringBuffer sb = new StringBuffer();
// 超过 120 个字符的情况下,不要在括号前换行
sb.append("zi").append("xin")...append
    ("huang");

// 参数很多的方法调用可能超过 120 个字符,不要在逗号前换行
method(args1, args2, args3, ...
    , argsX);
  1. 【强制】方法参数在定义和传入时,多个参数逗号后边必须加空格。
    正例:下例中实参的" a ",后边必须要有一个空格。
method("a", "b", "c");
  1. 【强制】 IDE 的 text file encoding 设置为 UTF -8 ; IDE 中文件的换行符使用 Unix 格式,不要使用 Windows 格式。

  2. 【推荐】没有必要增加若干空格来使某一行的字符与上一行对应位置的字符对齐。
    正例:

int a = 3;
long b = 4L;
float c = 5F;
StringBuffer sb = new StringBuffer();

说明:增加 sb 这个变量,如果需要对齐,则给 a 、 b 、 c 都要增加几个空格,在变量比较多的情况下,是一种累赘的事情。

  1. 【推荐】方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间插入一个空行。相同业务逻辑和语义之间不需要插入空行。
    说明:没有必要插入多个空行进行隔开。
额外
文档注释标签

Java 语言规范还定义了一种特殊的注释,叫文档注释(doc comment),这种注释用于编写代码 API 的文档。

  • 以 /** 开头(不是通常使用的 /*),以 */ 结尾。文档注释放在类型或成员定义的前面,其中的内容是那个类型或成员的文档。
  • 文档注释的描述性内容可以包含简单的 HTML 标记标签,例如: 用于强调, 用于显示类、方法和字段的名称,
     用于显示多行代码示例。除此之外,也可以包含 

    标签,把说明分成多个段落;还可以使用

    • 等相关标签,显示无序列表等结构。不过,要记住,你编写的内容会嵌入复杂的大型 HTML 文档,因此,文档注释不能包含 HTML 主结构标签,例如


      ,以防影响那个大型 HTML 文档的结构。

  • @author name
    添加一个“Author:”条目,内容是指定的名字。每个类和接口定义都应该使用这个标签,但单个方法和字段一定不能使用。如果一个类有多位作者,在相邻的几行中使用多个 @author 标签。

  • @version text
    插入一个“Version:”条目,内容是指定的文本。例如:
    @version 1.32, 08/26/04
    每个类和接口的文档注释中都应该包含这个标签,但单个方法和字段不能使用。这个标签经常和支持自动排序版本号的版本控制系统一起使用,例如 git、Perforce 或 SVN。

  • @param parameter-name description
    把指定的参数及其说明添加到当前方法的“Parameters:”区域。在方法和构造方法的文档注释中,每个参数都要使用一个 @param 标签列出,而且应该按照参数传入方法的顺序排列。这个标签只能出现在方法或构造方法的文档注释中。

  • @return description
    插入一个“Returns:”区域,内容是指定的说明。每个方法的文档注释中都应该使用这个标签,除非方法返回 void,或者是构造方法。为了保持简短,建议使用句子片段。

@return true:成功插入
        false:列表中已经包含要插入的对象
  • @exception full-classname description
    添加一个“Throws:”条目,内容是指定的异常名称和说明。方法和构造方法的文档注释应该为 throws 子句中的每个已检异常编写一个 @exception 标签。如果方法的用户基于某种原因想捕获当前方法抛出的未检异常(即 RuntimeException 的子类),@exception 标签也可以为这些未检异常编写文档。如果方法能抛出多个异常,要在相邻的几行使用多个 @exception 标签,而且按照异常名称的字母表顺序排列。这个标签只能出现在方法和构造方法的文档注释中。

  • @throws full-classname description
    这个标签是 @exception 标签的别名。

  • @see reference
    添加一个“See Also:”条目,内容是指定的引用。这个标签可以出现在任何文档注释中。

  • @deprecated explanation
    这个标签指明随后的类型或成员弃用了,应该避免使用。javadoc 会在文档中添加一个明显的“Deprecated”条目,内容为指定的 explanation 文本。这个文本应该说明这个类或成员从何时开始弃用,如果可能的话,还要推荐替代的类或成员,并且添加指向替代的类或成员的链接。
    一般情况下,javac 会忽略所有注释,但 @deprecated 标签是个例外。如果文档注释中有这个标签,编译器会在生成的类文件中注明弃用信息,提醒其他类,这个功能已经弃用。

  • @since version
    指明类型或成员何时添加到 API 中。这个标签后面应该跟着版本号或其他形式的版本信息。例如:@since JDK1.0
    每个类型的文档注释都应该包含一个 @since 标签;类型初始版本之后添加的任何成员,都要在其文档注释中加上 @since 标签。

行内文档注释标签

只要能使用 HTML 文本的地方都可以使用行内标签。因为这些标签直接出现在 HTML 文本流中,所以要使用花括号把标签中的内容和周围的 HTML 文本隔开。javadoc 支持的行内标签包括如下几个。

  • {@link reference }
    {@link}标签和 @see标签的作用类似,但 @see 标签是在专门的“See Also:”区域放一个指向引用的链接,而 {@link}标签在行内插入链接。在文档注释中,只要能使用 HTML 文本的地方都可以使用{@link} 标签。
    例如: @param regexp 搜索时使用的正则表达式。这个字符串参数使用的句法必须符合{@link java.util.regex.Pattern}制定的规则。

  • {@linkplain reference }
    {@linkplain}标签和{@link}标签的作用类似,不过,在{@linkplain} 标签生成的链接中,链接文字使用普通的字体,而{@link}标签使用代码字体。如果 reference 包含要链接的 feature 和指明链接替代文本的 label,就要使用 {@linkplain} 标签。

  • {@inheritDoc}
    如果一个方法覆盖了超类的方法,或者实现了接口中的方法,那么这个方法的文档注释可以省略一些内容,让 javadoc 自动从被覆盖或被实现的方法中继承。{@inheritDoc}标签可以继承单个标签的文本,还能在继承的基础上再添加一些说明。继承单个标签的方式如下:

@param index @{inheritDoc}
@return @{inheritDoc}
  • {@docRoot}
    这个行内标签没有参数,javadoc生成文档时会把它替换成文档的根目录。这个标签在引用外部文件的超链接中很有用,例如引用一张图片或者一份版权声明:
    这份资料受版权保护

  • {@literal text }
    这个行内标签按照字面形式显示texttext 中的所有 HTML 都会转义,而且所有javadoc标签都会被忽略。虽然不保留空白格式,但仍适合在

     标签中使用。

  • {@code text }
    这个标签和 {@literal} 标签的作用类似,但会使用代码字体显示 text 的字面量。

  • {@value}
    没有参数的 {@value} 标签在 static final 字段的文档注释中使用,会被替换成当前字段的常量值。

  • {@value reference }
    这种 {@value}标签的变体有一个reference参数,指向一个static final字段,会被替换成指定字段的常量值。

包的文档注释
  • javadoc 会在包所在的目录(存放包中各个类的源码)中需找一个名为 package.html 的文件,这个文件中的内容就是包的文档。
  • package.html 文件可以包含简单的HTML格式文档,也可以使用 @see@link@deprecated@since 标签。因为 package.html 不是 Java 源码文件,所以其中的文档应该是 HTML,而不能是 Java 注释(即不能包含在 /** 和 */ 之间)。最后,在 package.html 文件中,所有 @see@link 标签都必须使用完全限定的类名。

额外补充

  • 使用标准大括号样式
    我们需要在条件语句周围添加大括号。例外情况:如果整个条件语句(条件和主体)适合放在同一行,那么可以(但不是必须)将其全部放在一行上。例如,我们接受以下样式:
// 非常规范
if (condition) {
    body();
}

// 同样也接受以下样式:
if (condition) body();

但不接受以下样式:

if (condition)
    body();  // bad!
  1. 编写简短方法
    在可行的情况下,尽量编写短小精炼的方法。我们了解,有些情况下较长的方法是恰当的,因此对方法的代码长度没有做出硬性限制。如果某个方法的代码超出 40 行,请考虑是否可以在不破坏程序结构的前提下对其拆解。

  2. 类成员的顺序
    这并没有唯一的正确解决方案,但如果都使用一致的顺序将会提高代码的可读性,推荐使用如下排序:

  1. 常量
  2. 字段
  3. 构造函数
  4. 重写函数和回调
  5. 公有函数
  6. 私有函数
  7. 内部类或接口

例如:

public class MainActivity extends Activity {
    private static final String TAG = MainActivity.class.getSimpleName();
    private String mTitle;
    private TextView mTextViewTitle;
    @Override
    public void onCreate() {
        ...
    }
    public void setTitle(String title) {
        mTitle = title;
    }
    private void setUpView() {
        ...
    }
    static class AnInnerClass {
    }
}

如果类继承于 Android 组件(例如 Activity 或 Fragment),那么把重写函数按照他们的生命周期进行排序是一个非常好的习惯,例如,Activity 实现了 onCreate()、onDestroy()、onPause()、onResume(),它的正确排序如下所示:

public class MainActivity extends Activity {
    //Order matches Activity lifecycle
    @Override
    public void onCreate() {}
    @Override
    public void onResume() {}
    @Override
    public void onPause() {}
    @Override
    public void onDestroy() {}
}
  1. 换行策略
    这没有一个准确的解决方案来决定如何换行,通常不同的解决方案都是有效的,但是有一些规则可以应用于常见的情况。

    1. 操作符的换行
      除赋值操作符之外,我们把换行符放在操作符之前,例如:
    int longName = anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne
        + theFinalOne;
    

    赋值操作符的换行我们放在其后,例如:

    int longName =
        anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne + theFinalOne;
    
    1. 函数链的换行
      当同一行中调用多个函数时(比如使用构建器时),对每个函数的调用应该在新的一行中,我们把换行符插入在.之前
      例如:
    Picasso.with(context).load("https://blankj.com/images/avatar.jpg").into(ivAvatar);
    

    我们应该使用如下规则:

    Picasso.with(context)
        .load("https://blankj.com/images/avatar.jpg")
        .into(ivAvatar);
    
    1. 多参数的换行
      当一个方法有很多参数或者参数很长的时候,我们应该在每个 , 后面进行换行。
      比如:
    loadPicture(context,
        "https://blankj.com/images/avatar.jpg",
        ivAvatar,
        "Avatar of the user",
        clickListener);
    
  2. (安卓)Activities 和 Fragments 的传参
    当 Activity 或 Fragment 传递数据通过 Intent 或 Bundle 时,不同值的键须遵循上一条所提及到的。
    当 Activity 或 Fragment 启动需要传递参数时,那么它需要提供一个 public static 的函数来帮助启动或创建它。
    这方面,AS 已帮你写好了相关的 Live Templates,启动相关 Activity 的只需要在其内部输入 starter 即可生成它的启动器,如下所示:

public static void start(Context context, User user) {
      Intent starter = new Intent(context, MainActivity.class);
      starter.putParcelableExtra(EXTRA_USER, user);
      context.startActivity(starter);
}

同理,启动相关 Fragment 在其内部输入 newInstance 即可,如下所示:

public static MainFragment newInstance(User user) {
      Bundle args = new Bundle();
      args.putParcelable(ARGUMENT_USER, user);
      MainFragment fragment = new MainFragment();
      fragment.setArguments(args);
      return fragment;
}

注意:这些函数需要放在 onCreate() 之前的类的顶部;如果我们使用了这种方式,那么 extras 和 arguments 的键应该是 private 的,因为它们不再需要暴露给其他类来使用。

Ref:
Android 开发规范(完结版) | Blankj's Blog https://blankj.com/2017/03/08/android-standard-dev-final/

阿里巴巴 Java技术手册最终版

你可能感兴趣的:(阿里Java编程规约【三】代码格式)