Oracle规范for java

Oracle规范笔记

摘自:https://www.oracle.com/technetwork/java/codeconvtoc-136057.html

1. 介绍

1.1为什么要规范

  1. 80%的时间用于软件的维护
  2. 任何软件很难一直被原始作者维护
  3. 代码规范提升程序的可读性,让工程师可以更快、更全面的理解代码
  4. 如果要将源码作为产品推向市场,需要确保它像其他的产品一样包装玩好且代码整洁

2.文件名

2.1文件后缀
源码文件(Java source)->.java
字节码文件(Java bytecode)->.class
2.2 一些通用的文件
File Name Use
GNUmakefile 构建软件(不是很了解,后期需要学习)
README 总结特定目录的文件名

3.文件组织

  一个文件由很多节组成,节与节之间用一些空行和一个能够区分每个节的注释分割(注释可有可无)。
  行数超过2000的文件是冗长的,不易操作。
  例子请见下面的“源文件举例”。
3.1Java源文件
  每一个java源文件含有一个public类或者是接口。当private类和接口与public类相关时,可以把它们放在public类所在源文件。public类必须是文件中第一个类或接口。
java源文件有以下要求:

  • 起始注释(后面介绍)
  • Package和Import语句
  • 类与接口的声明

3.1.1起始注释
  所有的源文件能够以c注释格式开始,c-style含有类名,版本信息、数据和版权布告:

/*
 *Classname
 *
 *Version information
 *
 *Date
 *
 *Copyright
 */

3.1.2Package和Import语句
  第一行非注释代码是package语句。紧接着是import语句,举例:

package java.awt;
import java.awt.peer.CanvasPeer;

3.1.3类和接口的声明

  • 类和接口的文件注释 /**…*/
  • 类和接口的实现注释 /**…*/

4.缩进

  四个空格作为缩进的一个单元。具体的缩进结构不确定。Tabs必须与8个空格等同。
4.1行的长度
避免一行的字符超过80个,因为这样不能够很好地被许多终端和工具处理。
**注:**文档中的例子使用更短的行长,不超过70,换行符算一个字符。
4.2换行
 emsp;当不适合单行时,用下面的几条规则:

  • 在逗号处分割
  • 在运算符前分割
  • 分割有优先级,高级先于低级
  • 新的行与上一行对齐(同级)
  • 如果上述准则导致了易混淆的代码或者代码被右侧的空白挤扁了,就只用八个空格分割

  这里有一些例子:

someMethod(longExpression1, longExpression2, longExpression3, 
        longExpression4, longExpression5);
 
var = someMethod1(longExpression1,
                someMethod2(longExpression2,
                        longExpression3));

  下面的两种打断算数的方法。第一种更好,因为打断在被括号的表达式之外,是更高的等级。

longName1 = longName2 * (longName3 + longName4 - longName5)
           + 4 * longname6; // PREFER

longName1 = longName2 * (longName3 + longName4
                       - longName5) + 4 * longname6; // AVOID 

  下面是两个方法声明的例子。第一种是规范的情况。第二种将第二行和第三行如果规范化缩进,将会让代码过于靠右,所以用8个空格缩进。

//CONVENTIONAL INDENTATION
someMethod(int anArg, Object anotherArg, String yetAnotherArg,
           Object andStillAnother) {
    ...
}

//INDENT 8 SPACES TO AVOID VERY DEEP INDENTS
private static synchronized horkingLongMethodName(int anArg,
        Object anotherArg, String yetAnotherArg,
        Object andStillAnother) {
    ...
}

  对于if语句的换行应该用8-space规则,因为常规方法不易分辨主体(body):

//DON'T USE THIS INDENTATION
if ((condition1 && condition2)
    || (condition3 && condition4)
    ||!(condition5 && condition6)) { //BAD WRAPS
    doSomethingAboutIt();            //MAKE THIS LINE EASY TO MISS
} 

//USE THIS INDENTATION INSTEAD
if ((condition1 && condition2)
        || (condition3 && condition4)
        ||!(condition5 && condition6)) {
    doSomethingAboutIt();
} 

//OR USE THIS
if ((condition1 && condition2) || (condition3 && condition4)
        ||!(condition5 && condition6)) {
    doSomethingAboutIt();
}

对于三元的表达式的方法:

alpha = (aLongBooleanExpression) ? beta : gamma;  

alpha = (aLongBooleanExpression) ? beta
                                 : gamma;  

alpha = (aLongBooleanExpression)
        ? beta 
        : gamma; 

5.注释

  Java程序含有两种注释:实现注释(Implement comments)和文档注释(documentation comments)。实现注释与c++相同,用//和//分割,文档注释“/**…*/”只用于java中,文档注释能够利用javadoc工具生成HTML文件。
  实现注释是用于特定的方法实现,文档注释在实现代码之外,能够被开发人员读到并明确谁有必要使用源代码。
  注释提供代码的概况并提供在代码中不能够看出的额外信息。注释只包含帮助阅读和理解代码的信息。举例来说,代码在哪个目录中、由哪个包创建不必作为注释出现。
  不普通和和不明显的设计是应该的,但是应该避免重复表示信息。注释应该容易与代码区分。总之,避免随着代码增多,避免代码与注释分离。
**注:**注释的频率有时反应不好的代码质量。当你感到应该添加注释时,考虑重写代码使代码更加啊整洁。

注释不应该大段地被星号和其他字符包围
注释不应该包含换页符和回车
5.1实现注释格式
程序有4种实现注释:块、单行
5.1.1块
  用来描述文件、方法、数据结构和算法。块代码可能会被用在每个文件或方法的开头,它们也可以用在方法内等地方。在函数或方法内部的块注释应该首行缩进至与它所描述的代码同级。
  注释块应该先于其余代码一个空行。

/*
 * Here is a block comment.
 */



/*-indent

<blockquote>/*-
 * Here is a block comment with some very special
 * formatting that I want indent(1) to ignore.
 *
 *    one
 *        two
 *            three
 */

**注:**缩进策略与前面介绍的相同。
5.1.2单行注释
短的单行注释在代码之前,如果注释不能在一行中写下,那就遵循块注释的风格。一个单行注释必须以一个空行为前导。

if (condition) {

    /* Handle the condition. */
    ...
}

5.1.3尾端注释(trailing comments)
尾端注释与代码出现在同一行,但必须挪动足够离远语句以便分辨。对于一大段代码中不止一行代码需要注释,那么注释的缩进应该用相同的tab setting。

if (a == 2) {
    return TRUE;            /* special case */
} else {
    return isPrime(a);      /* works only for odd a */
}

5.1.4行尾注释
//用来注释一行或部分行,不应该多行连续注释说明文档;然而,可以多行连续注释代码段。

if (foo > 1) {

    // Do a double-flip.
    ...
}
else {
    return false;          // Explain why here.
}
//if (bar > 1) {
//
//    // Do a triple-flip.
//    ...
//}
//else {
//    return false;
//}

5.2 文档注释
如何写文档注释(@return, @param, @see)

/**
 * Returns an Image object that can then be painted on the screen. 
 * The url argument must specify an absolute {@link URL}. The name
 * argument is a specifier that is relative to the url argument. 
 * <p>
 * This method always returns immediately, whether or not the 
 * image exists. When this applet attempts to draw the image on
 * the screen, the data will be loaded. The graphics primitives 
 * that draw the image will incrementally paint on the screen. 
 *
 * @param  url  an absolute URL giving the base location of the image
 * @param  name the location of the image, relative to the url argument
 * @return      the image at the specified URL
 * @see         Image
 */
 public Image getImage(URL url, String name) {
        try {
            return getImage(new URL(url, name));
        } catch (MalformedURLException e) {
            return null;
        }
 }

  注意类和接口前面的的注释不缩进,(/**)不缩进,但随后的文档注释应该缩进一个空格(与星号对齐)成员包括构造器,首行缩进4个空格,其后缩进5个空格。

  当不适合用文档注释时,可以用实现注释代替注释后一行紧跟着它的声明。

6.声明

6.1每行的数量
  推荐一行一个声明,因为这样便于注释。换句话说,

int level; // indentation level
int size;  // size of table

好于

int level, size;

不要把不同的类型放在同一行,例如:

int foo,  fooarray[]; //WRONG!

**注:**可以用tabs代替空格

int     level;          // indentation level
int     size;            // size of table
Object  currentEntry;    // currently selected table entry

6.2初始化
  尽量在声明的地方初始化,除非需要经历计算。

6.3位置
  在块开始的地方进行声明(被花括号包围)。不要在用到时才进行初始化,那样会迷惑不敏感的程序员,阻碍一定范围内代码的可移植性。

void myMethod() {
    int int1 = 0;         // beginning of method block

    if (condition) {
        int int2 = 0;     // beginning of "if" block
        ...
    }
}
</blockquote>

  显然循环是不同的:

for (int i = 0; i < maxLoops; i++) { ... }
</blockquote>

  避免隐藏更高级别声明的本地声明,例如,不能够在内部块中声明相同的变量名。

int count;
...
myMethod() {
    if (condition) {
        int count = 0;     // AVOID!
        ...
    }
    ...
}

6.4类和接口的声明
下面是一些规则:

  • 方法名与(之间没有空格
  • {与声明语句同一行
  • }独自一行,如果块内没有语句,那么}紧接着{;
class Sample extends Object {
    int ivar1;
    int ivar2;

    Sample(int i, int j) {
        ivar1 = i;
        ivar2 = j;
    }

    int emptyMethod() {}

    ...
}

方法被空行分割

7.语句

7.1简单语句
一行最多含有一条语句

argv++;         // Correct
argc--;         // Correct  
argv++; argc--; // AVOID!

7.2复合语句
复合语句是包含一系列的被“{}”包含的块

  • 被包围语句比复合语句深入一个等级
  • 前花括号紧接着复合语句,后花括号与复合语句开头对齐
  • 单行也应该加花括号

7.3返回语句
尽量不用括号

return;

return myDisk.size();

return (size ? size : defaultSize);

7.4if else

if (condition) {
    statements;
}

if (condition) {
    statements;
} else {
    statements;
}

if (condition) {
    statements;
} else if (condition) {
    statements;
} else {
    statements;
}

避免

if (condition) //AVOID! THIS OMITS THE BRACES {}!
    statement;

7.5for语句

for (initialization; condition; update) {
    statements;
}

空循环体

for (initialization; condition; update);

7.6while语句

while (condition) {
    statements;
}

空循环体

while (condition);

7.7do-while语句

do {
    statements;
} while (condition);

7.8 switch语句

switch (condition) {
case ABC:
    statements;
    /* falls through */
case DEF:
    statements;
    break;
case XYZ:
    statements;
    break;
default:
    statements;
    break;
}

7.9 try-catch Statements

try {
    statements;
} catch (ExceptionClass e) {
    statements;
} finally {
    statements;
}

8.空白

8.1空行
两行空白:

  • 源文件的节
  • 类与接口的定义

一行空白:

  • 方法间
  • 本地方法变量和第一个语句间
  • 一段代码与单行注释
  • 在逻辑块间增加可读性

8.2空格

  • 关键字与括号之间需要一个空格
       while (true) {
           ...
       }
  • 逗号之后
  • 所有的二元运算符
    a += c + d;
    a = (a + b) / (c * d);
    
    while (d++ = s++) {
        n++;
    }
    printSize("size is " + foo + "\n");
  • for语句之间的表达式用空格分割
    for (expr1; expr2; expr3)
  • 转化之后接一个空格
    myMethod((byte) aNum, (Object) x);
    myMethod((int) (cp + 5), ((int) (i + 3)) 
                                  + 1);

9.命名规范

Packages:全为小写字母

com.sun.eng

com.apple.quicktime.v2


edu.cmu.cs.bovik.cheese

Classes:类名应该是名词,大小写混合,简单并且描述性好,避免使用首字母缩略,除非缩写形式被更加广泛的使用

class Raster; 
class ImageSprite;

Interfaces:和类名一样
Methods:方法名应该为动词,小写字母开头,大小写混合

Methods should be verbs, in mixed case with the first letter lowercase, with the first letter of each internal word capitalized.

Variables:变量名要短小并且有实际意义,应该是帮助记忆的词汇单个字母的变量名应该避免,除非很快抛弃( i, j, k, m, and n for integers; c, d, and e for characters.)
Constants:

static final int MIN_WIDTH = 4;

static final int MAX_WIDTH = 999;

static final int GET_THE_CPU = 1;


10.编程实践

10.1获取对象和类的变量
  不要无缘无故地将任何变量或类的变量为public,实例对象不需要明确地设置和频繁地获取,就像方法调用的副作用一样。
  如果用struct,那么久可以都定义为public。
10.2对类中变量和方法的的索引
避免用一个对象来获取类的变量和方法。用类名代替,举例:

classMethod();             //OK
AClass.classMethod();      //OK
anObject.classMethod();    //AVOID!

10.3常量
数字常量不应该直接编码,除了-1,0,和1,能够在for语句中充当计数器。
10.4变量赋值
避免给多个变量在一行中赋相同的值。那是不易阅读的。
Example:

fooBar.fChar = barFoo.lchar = 'c'; // AVOID!

避免在易于与等号混淆的地方用到赋值符号。

if (c++ = d++) {        // AVOID! (Java disallows)
    ...
}
</blockquote>

应该写为

if ((c++ = d++) != 0) {
    ...
}

不要将赋值语句镶嵌以提升运行性能。这是编译器的工作(compiler)。Example:

d = (a = b + c) + r;        // AVOID!
</blockquote>

应该写为:

a = b + c;
d = a + r;

10.5混杂的 联系
10.5.1括号
即使优先级是很清楚的,也应该加入括号,确保阅读代码的人也能明白优先级。

if (a == b && c == d)     // AVOID!
if ((a == b) && (c == d)) // RIGHT

10.5.2返回值
让你代码的结构复合期望

if (
             booleanExpression) {
    return true;
} else {
    return false;
}

应该写为:

return  
             booleanExpression;
if (condition) {
    return x;
}
return y;

应该写为:

return (condition ? x : y);

10.5.3在‘?’之前的表达式
当?前的表达是一个二元运算时,应该用括号。Example:
(x >= 0) ? x : -x;
10.5.4特殊注释
用XXX在注释中来标记有些东西是假的但是可以工作。用FIXME来 标记有问题的。

11.代码举例

/*
 * @(#)Blah.java        1.82 99/03/18
 *
 * Copyright (c) 1994-1999 Sun Microsystems, Inc.
 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of Sun
 * Microsystems, Inc. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Sun.
 */


package java.blah;

import java.blah.blahdy.BlahBlah;

/**
 *  
         Class description goes here.
 *
 * @version      
         1.82 18 Mar 1999  * @author          
         Firstname Lastname  */
public class Blah extends SomeClass {
  
            /* A class implementation comment can go here. */ 
    /**  
         classVar1 documentation comment */
    public static int classVar1;

    /** 
  
             *  
         classVar2 documentation comment that happens to be      *  
         more than one line long      */
    private static Object classVar2;

    /**  
         instanceVar1 documentation comment */
    public Object instanceVar1;

    /**  
         instanceVar2 documentation comment */
    protected int instanceVar2;

    /**  
         instanceVar3 documentation comment */
    private Object[] instanceVar3;

    /** 
     * ...
         constructor Blah documentation comment...      */
    public Blah() {
  
               // ...implementation goes here...     }

    /**
     * ...
         method doSomething documentation comment...      */
    public void doSomething() {
  
                // ...implementation goes here...      }

    /**
     * ...method doSomethingElse  
         documentation comment...      * @param someParam  
         description      */
    public void doSomethingElse(Object someParam) {
  
                // ...implementation goes here...      }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值