java开发规范
主要参考了阿里巴巴开发规范,特此说明
一、通用规范
1、注释
总体原则是: 对外接口必须写;内部接口不建议使用 ,如果名字已经可以解释其意义,则不需要加注释,如果不能解释则可以加
1)属性注释
/** xxx **/private String name;public void setName(String name){ //xxx do();}2、文件结构
1)类的成员顺序:public > private > final > static > 实例成员;类结构:成员 > 构造方法 > 静态方法 > 实例方法
说明:通常使用者会更关注public 属性/方法
public class User{ public final static String key1='key1'; public static String key2="key2"; public String key3="key3"; private String key4="key4"; public User(){ } public static void setKey3(String key3){ } public void setKey4(String key4){ } private void foo(){ }}2)列限制:200,尽量在一行显示完整,超出需要换行,换行时遵循如下原则:
a 第二行相对第一行缩进 4 个空格,从第三行开始,不再继续缩进,参考示例。
b 运算符与下文一起换行。
c 方法调用的点符号与下文一起换行。
sb.append("zi").append("xin")... .append("huang")... .append("huang")... .append("huang");
d 在多个参数超长,逗号后进行换行。
e 在括号前不要换行,如下反例
method(args1, args2, args3, ... ,argsX);public static String name;private int id;public void method1(){}public void method2(){}3、命名规范
不能使用拼音进行命名,统一使用准确的英文进行命名
不采用简写方式命名(除公认的常用简写,或公司/小组字典表有描述)。命名过长比不能理解更好
1)、包名
2)、接口与类的命名
接口不要以 I 开头。如:IUserService,而直接采用具体的命名方式如UserService
3)、抽象类命名
抽象类命名使用:Abstract+名词的方式进行命名,如:AbstractMessage
4)、实现类命名
a 基于 SOA 的理念,暴露出来的服务一定是接口,内部的实现类用 Impl 的后缀与接口区别。例如UserServiceImpl
b 对于只有一个实现类的情况(外部接口除外),通常先不采用接口方式,直接采用实现类即可
c 如果有多个实现类,则采用名称+抽象名称+Impl,如UserMessageImpl、AdminMessageImpl
5)、变量命名
a 所有变量(描述状态的除外)统一以准确的名词性英文命名,名词性英文语法如下:
- 普通名词,如:user、clubMember、order等
- 组合名词,即名词+名词,如:clubMemberServiceOrder,paymentResult等
- 带修饰语(定语)名词,如:checkingResult,messageSendingTask(主动,用ing),closedOrder(已经关闭的订单,用ed)
b 描述状态的变量统一以准确的形容词性英文命名,形容词性英文语法如下:
- 普通形容词,如:active,inactive,valid,invalid等
- 动词转形容词,表示状态,如:close > closed,stop > stopped等
- 动词转形容词,标示能动,如:delete > deletable,use > useful等
c 对于反映状态的变量,不要在命名前面加“is”,因为自动生成的get方法,对于boolean值,方面名自动会变为is***
常量用全大写,单词之间用“_”分割,如:
public static final String QUERYCLUBMEMBER_HQL=”…”;
d 对于成员变量,其名称可省略所属类的名称,如:
public class User { private String userName; //NOT GOOD private String name; //GOOD}- 方法名命名规则:
- 动词:init,validate,pay等
- 动词+介词+(宾语):compareTo,getById等
- 动宾短语(表示动作):createUser,publishPrivilege
- 谓表短语(表示状态):isClosed,isUserExisted,canUserBeDeleted等
-
接口类中的方法和属性不要加任何修饰符号 (public 也不要加 ,保持代码的简洁性)
- 单复数的使用,对于一些动作需要操作多个对象,方法名要通过名词复数反映出来,例如:deleteOrders(删除订单,可能多个)
- 如果一个方法设计两个动作或对象,用“And”连接,如:createProductAndTag,但一般情况下,不推荐一个方法做多于一件事情
- 不要使用简写,除非是公司级别或者业界已经通用的约定或字典表定义表示 ,比如I18n,则可以使用。因为简写很难阅读,容易误解,宁愿方法名稍微长一些,也要让方法名用正确的短语来表述,由于一个方法一般不建议做多于一件事情,所以方法名一般不会太长
- 一些Java业界约定俗成的方法命名:
- 与…进行比较:compareTo
- 获取单例对象:getInstance
- 是否相等:equals
- 初始化:init
- 对于dao层,其名称可省略所属类的名称,如:
public interface UserDao { int createUser(User user); //NOT GOOD int create(User user); //GOOD}接口、类的命名约定 |
类名
|
命名
|
示例
|
|---|---|---|
| Controller类 | **Controller | OrderController |
| DAO层 | **Dao | UserDao |
| Entity(领域对象) | 实体名 | User |
| Interceptor类 | **Interceptor | AuthenticationInterceptor |
| Servlet Filter类 | **Filter | ApplicationContextFilter |
| Servlet类 | **Servlet | SystemInitServlet |
| VO/DTO(视图对象) | 实体名+VO | UserVO |
| 工具类命名 | ***Util | DateUtil |
| 系统监控器类 | **Monitor | MemcachedMonitor |
| 逻辑层类 | **Service | UserService |
b POJO 类命名约定
POJO类包含了Entity、VO。POJO 类中布尔类型的变量,都不要加 is ,否则部分框架解析会引起序列化错误。
c 常规方法的命名约定
|
方法名
|
示例
|
批量
|
备注
|
|---|---|---|---|
| 列表 | list***(复数) listUsers | - | 如果返回为空,则返回size=0的list,不能返回null |
| 创建 | create*** create createUser | batchCreate**s batchCreateUsers | |
| 删除 | delete** delete deleteUser | batchDelete**s batchDeleteUsers | |
| 更新 | update** update updateUser | batchUpdate**s batchUpdateUsers | |
| 统计 | count*** | batchCount*** | |
| 获取单个对象 | get** get getUser | batchGet**s batchGetUsers | |
| 获取单个对象根据某个参数 | getBy** getByName | - |
- 不要使用一个常量类维护所有常量,应该按常量功能进行归类,分开维护。如:缓存相关的常量放在类: CacheConsts 下 ; 系统配置相关的常量放在类: ConfigConsts 下。
说明:大而全的常量类,非得使用查找功能才能定位到修改的常量,不利于理解和维护。
- 常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量。
- 跨应用共享常量:放置在二方库中,通常是 client . jar 中的 constant 目录下。
- 应用内共享常量:放置在一方库的 modules 中的 constant 目录下。
- 反例:易懂变量也要统一定义成应用内共享常量,两位攻城师在两个类中分别定义了表示“是”的变量:
- 类 A 中: public static final String YES = " yes " ;
- 类 B 中: public static final String YES = " y " ;
- A . YES . equals(B . YES) ,预期是 true ,但实际返回为 false ,导致产生线上问题。
- 子工程内部共享常量:即在当前子工程的 constant 目录下。
- 包内共享常量:即在当前包下单独的 constant 目录下。
- 类内共享常量:直接在类内部 private static final 定义
7)、控制语句
a 在一个 switch 块内,每个 case 要么通过 break / return 等来终止,要么注释说明程序将继续执行到哪一个 case 为止 ; 在一个 switch 块内,都必须包含一个 default 语句并且放在最后,即使它什么代码也没有。
b 在 if / else / for / while / do 语句中必须使用大括号,即使只有一行代码,避免使用下面的形式: if (condition) statements;
c 推荐尽量少用 else , if - else 的方式可以改写成:
if (condition) { ... return obj;}boolean existed = (file.open(fileName, "w") != null) && (...) || (...);if (existed) { ...}//NOT GOODpublic int insertUser() { String name=request.get("name"); String password=request.get("password");}//GOODpublic int insertUser(String name,String password) {}二、业务规范
正例: " test " .equals(object);
反例: object.equals( " test " );
说明:推荐使用 java . util . Objects # equals (JDK 7 引入的工具类 )
说明:对于 Integer var = ?在-128 至 127 之间的赋值, Integer 对象是在IntegerCache . cache 产生,会复用已有对象,这个区间内的 Integer 值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。
说明:在方法执行抛出异常时,可以直接调用 POJO 的 toString() 方法打印其属性值,便于排查问题。
说明:公有方法是类的调用者和维护者最关心的方法,首屏展示最好 ; 保护方法虽然只是子类关心,也可能是“模板设计模式”下的核心方法 ; 而私有方法外部一般不需要特别关心,是一个黑盒实现 ; 因为方法信息价值较低,所有 Service 和 DAO 的 getter / setter 方法放在类体最后。
public class TimerTaskThread extends Thread { public TimerTaskThread() { super.setName("TimerTaskThread"); ...}说明:注意,子线程抛出异常堆栈,不能在主线程 try - catch 到。
三、极致函数
1、不超过100行
2、嵌套层次不超过3层
例如if else try for while等这些控制代码的层次不能过深,否则可读性将会变得很差。尽量保持平级,尽早返回或跳出。
3、一个函数不超过2个功能的具体代码,可以是引用
如果函数内有多个功能的具体代码,会造成临时变量过多,并且这些变量大多是无相关的。会造成命名困难与容易引用变量出错。
浙公网安备 33010602011771号