基于阿里巴巴JAVA开发规范整理java
【强制】类名使用 UpperCamelCase 风格,必须听从驼峰形式,但如下情形例外:DO / BO / DTO / VO / AO程序员
正例:MarcoPolo / UserDO / XmlService / TcpUdpDeal / TaPromotion
反例:macroPolo / UserDo / XMLService / TCPUDPDeal / TAPromotion正则表达式
【强制】方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须听从 驼峰形式。数据库
正例: localValue / getHttpMessage() / inputUserId编程
【强制】常量命名所有大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。数组
正例:MAX_STOCK_COUNT 反例:MAX_COUNT缓存
【强制】抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类命名以它要测试的类的名称开始,以 Test 结尾。微信
【强制】Model 类中布尔类型的变量,都不要加 is,不然部分框架解析会引发序列化错误。数据结构
反例:定义为基本数据类型 Boolean isDeleted;的属性,它的方法也是 isDeleted(),RPC框架在反向解析的时候,“觉得”对应的属性名称是 deleted,致使属性获取不到,进而抛出异常。并发
【强制】对于 Service 和 DAO 类,基于 SOA 的理念,暴露出来的服务必定是接口,内部的实现类用 Impl 的后缀与接口区别。 正例:CacheManagerImpl 实现 CacheManager 接口。
【推荐】为了达到代码自解释的目标,任何自定义编程元素在命名时,使用尽可能完整的单词组合来表达其意。
正例:从远程仓库拉取代码的类命名为PullCodeFromRemoteRepository
反例:变量int a;的随意命名方式。
正例:接口方法签名:void f(); 接口基础常量表示:String COMPANY = "alibaba";
反例:接口方法定义:public abstract void f();
说明:JDK8 中接口容许有默认实现,那么这个default方法,是对全部实现类都有价值的默 认实现。
【参考】枚举类名建议带上 Enum 后缀,枚举成员名称须要全大写,单词间用下划线隔开。
说明:枚举其实就是特殊的常量类,且构造方法被默认强制是私有。
正例:枚举名字为 ProcessStatusEnum 的成员名称:SUCCESS / UNKOWN_REASON。
【参考】各层命名规约:
A) Service/DAO 层方法命名规约
1) 获取单个对象的方法用 get 作前缀。
2) 获取多个对象的方法用 list 作前缀。
3) 获取统计值的方法用 count 作前缀。
4) 插入的方法用 save/insert 作前缀。
5) 删除的方法用 remove/delete 作前缀。
6) 修改的方法用 update 作前缀。
正例:缓存相关常量放在类 CacheConsts 下;系统配置相关常量放在类 ConfigConsts 下。
【强制】大括号的使用约定。若是是大括号内为空,则简洁地写成{}便可,不须要换行;若是 是非空代码块则:
1) 左大括号前不换行。
2) 左大括号后换行。
3) 右大括号前换行。
4) 右大括号后还有 else 等代码则不换行 表示终止的右大括号后必须换行。
【强制】 左小括号和字符之间不出现空格;一样,右小括号和字符之间也不出现空格。
反例:if (空格a == b空格)
【强制】if/for/while/switch/do 等保留字与括号之间都必须加空格。
【强制】任何二目、三目运算符的左右两边都须要加一个空格。
说明:运算符包括赋值运算符=、逻辑运算符&&、加减乘除符号等。
【强制】采用 4 个空格缩进,禁止使用 tab 字符。
说明:Vue工程采用2个空格缩进
【强制】注释的双斜线与注释内容之间有且仅有一个空格。
正例:// 注释内容,注意在//和注释内容之间有一个空格。
【强制】方法参数在定义和传入时,多个参数逗号后边必须加空格。
正例:下例中实参的"a",后边必需要有一个空格。method("a", "b", "c");
【强制】IDE 的 text file encoding 设置为 UTF-8; IDE 中文件的换行符使用 Unix 格式,不要使用 Windows 格式。
【推荐】方法体内的执行语句组、变量的定义语句组、不一样的业务逻辑之间或者不一样的语义之间插入一个空行。相同业务逻辑和语义之间不须要插入空行。
说明:没有必要插入多个空行进行隔开。
【强制】全部的覆写方法,必须加@Override 注解。
【强制】不能使用过期的类或方法。
【强制】Object 的 equals 方法容易抛空指针异常,应使用常量或肯定有值的对象来调用 equals。
正例:"test".equals(object);
反例:object.equals("test");
【强制】全部的相同类型的包装类对象之间值的比较,所有使用 equals 方法比较。
说明:对于 Integer var = ? 在-128 至 127 范围内的赋值,Integer 对象是在IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer 值能够直接使用==进行判断,可是这个区间以外的全部数据,都会在堆上产生,并不会复用已有对象,这是一个大坑, 推荐使用 equals 方法进行判断。
【强制】RPC 方法的返回值和参数必须使用包装数据类型。
【强制】构造方法里面禁止加入任何业务逻辑,若是有初始化逻辑,请放在 init 方法中。
【推荐】当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一块儿, 便于阅读。
【推荐】循环体内,字符串的链接方式,使用 StringBuilder 的 append 方法进行扩展。 说明:反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,而后进行 append 操做,最后经过 toString 方法返回 String 对象,形成内存资源浪费。
反例:
String str = "start"; for (int i = 0; i < 100; i++) { str = str + "hello"; }
List<String> list = new ArrayList<String>(2); list.add("guan"); list.add("bao"); String[] array = new String[list.size()]; array = list.toArray(array);
反例:直接使用 toArray 无参方法存在问题,此方法返回值只能是 Object[]类,若强转其它 类型数组将出现 ClassCastException 错误。
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) { String item = iterator.next(); if (删除元素的条件) { iterator.remove(); } }
反例:
List<String> list = new ArrayList<String>(); list.add("1"); list.add("2"); for (String item : list) { if ("1".equals(item)) { list.remove(item); } }
【强制】在一个 switch 块内,每一个 case 要么经过 break/return 等来终止,要么注释说明程序将继续执行到哪个 case 为止;在一个 switch 块内,都必须包含一个 default 语句而且 放在最后,即便它什么代码也没有。
【强制】在 if/else/for/while/do 语句中必须使用大括号。即便只有一行代码,避 单行的编码方式:if (condition) statements;
【推荐】除经常使用方法(如 getXxx/isXxx)等外,不要在条件判断中执行其它复杂的语句,将复 杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提升可读性。 说明:不少 if 语句内的逻辑至关复杂,阅读者须要分析条件表达式的最终结果,才能明确什么 样的条件执行什么样的语句,那么,若是阅读者分析逻辑表达式错误呢?
正例: // 伪代码以下
final boolean existed = (file.open(fileName, "w") != null) && (...) || (...); if (existed) { ... }
反例:
if ((file.open(fileName, "w") != null) && (...) || (...)) { ... }
【强制】类、类属性、类方法的注释必须使用 Javadoc 规范,使用/**内容*/ 格式,不得使用 // xxx 方式。
【强制】全部的抽象方法(包括接口中的方法)必需要用 Javadoc 注释、除了返回值、参数、 异常说明外,还必须指出该方法作什么事情,实现什么功能。 说明:对子类的实现要求,或者调用注意事项,请一并说明。
【强制】全部的类都必须添加建立者和建立日期。
【强制】方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释 使用/* */注释,注意与代码对齐。
【强制】全部的枚举类型字段必需要有注释,说明每一个数据项的用途。
【推荐】代码修改的同时,注释也要进行相应的修改,尤为是参数、返回值、异常、核心逻辑 等的修改。 说明:代码与注释更新不一样步,就像路网与导航软件更新不一样步同样,若是导航软件严重滞后, 就失去了导航的意义。
【参考】谨慎注释掉代码。在上方详细说明,而不是简单地注释掉。若是无用,则删除。
【参考】对于注释的要求:第1、可以准确反应设计思想和代码逻辑;第2、可以描述业务含 义,使别的程序员可以迅速了解到代码背后的信息。彻底没有注释的大段代码对于阅读者形同 天书,注释是给本身看的,即便隔很长时间,也能清晰理解当时的思路;注释也是给继任者看 的,使其可以快速接替本身的工做。
【参考】好的命名、代码结构是自解释的,注释力求精简准确、表达到位。避免出现注释的 一个极端:过多过滥的注释,代码的逻辑一旦修改,修改注释是至关大的负担。
【参考】特殊注释标记,请注明标记人与标记时间。注意及时处理这些标记,经过标记扫描, 常常清理此类标记。线上故障有时候就是来源于这些标记处的代码。
1) 待办事宜(TODO):( 标记人,标记时间,[预计处理时间]) 表示须要实现,但目前还未实现的功能。这其实是一个 Javadoc 的标签,目前的 Javadoc 尚未实现,但已经被普遍使用。只能应用于类,接口和方法(由于它是一个 Javadoc 标签)。
2) 错误,不能工做(FIXME):(标记人,标记时间,[预计处理时间]) 在注释中用 FIXME 标记某代码是错误的,并且不能工做,须要及时纠正的状况。
【强制】在使用正则表达式时,利用好其预编译功能,能够有效加快正则匹配速度。 说明:不要在方法体内定义:Pattern pattern = Pattern.compile(规则);
【强制】注意 Math.random() 这个方法返回是 double 类型,注意取值的范围 0≤x<1(可以 取到零值,注意除零异常),若是想获取整数类型的随机数,不要将 x 放大 10 的若干倍而后 取整,直接使用 Random 对象的 nextInt 或者 nextLong 方法。
【强制】获取当前毫秒数 System.currentTimeMillis(); 而不是 new Date().getTime();
【推荐】任何数据结构的构造或初始化,都应指定大小,避免数据结构无限增加吃光内存。
【强制】表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只 出现数字。数据库字段名的修改代价很大,由于没法进行预发布,因此字段名称须要慎重考虑。
说明:MySQL 在 Windows 下不区分大小写,但在 Linux 下默认是区分大小写。所以,数据库 名、表名、字段名,都不容许出现任何大写字母,避免节外生枝。
正例:aliyun_admin,rdc_config,level3_name 反例:AliyunAdmin,rdcConfig,level_3_name
【强制】禁用保留字,如 desc、range、match、delayed 等,请参考 MySQL 官方保留字。
【强制】主键索引名为 pk_字段名;惟一索引名为 uk_字段名;普通索引名则为 idx_字段名。 说明:pk_ 即 primary key;uk_ 即 unique key;idx_ 即 index 的简称。
【强制】小数类型为 decimal,禁止使用 float 和 double。
【强制】若是存储的字符串长度几乎相等,使用 char 定长字符串类型。
【强制】varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,若是存储长度大于此值,定义字段类型为 text。
【强制】表必备三个字段:id,create_time, update_time, delete_flag
【强制】对于Boolean型的字段,采用decimal类型
【强制】表和字段都须要添加注释信息。
【推荐】单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。 说明:若是预计三年后的数据量根本达不到这个级别,请不要在建立表时就分库分表。
【参考】合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提高检 索速度。
【强制】业务上具备惟一特性的字段,即便是多个字段的组合,也必须建成惟一索引。
说明:不要觉得惟一索引影响了 insert 速度,这个速度损耗能够忽略,但提升查找速度是明 显的;另外,即便在应用层作了很是完善的校验控制,只要没有惟一索引,根据墨菲定律,必 然有脏数据产生。
【强制】超过三个表禁止 join。须要 join 的字段,数据类型必须绝对一致;多表关联查询时, 保证被关联的字段须要有索引。
说明:即便双表 join 也要注意表索引、SQL 性能。
【强制】在 varchar 字段上创建索引时,必须指定索引长度,不必对全字段创建索引,根据 实际文本区分度决定索引长度便可。
说明:索引的长度与区分度是一对矛盾体,通常对字符串类型数据,长度为 20 的索引,区分度会高达 90%以上,可使用 count(distinct left(列名, 索引长度))/count(*)的区分度 来肯定。
【参考】建立索引时避免有以下极端误解:
1)宁滥勿缺。认为一个查询就须要建一个索引。
2)宁缺勿滥。认为索引会消耗空间、严重拖慢更新和新增速度。
3)抵制唯一索引。认为业务的唯一性一概须要在应用层经过“先查后插”方式解决。
【强制】不要使用 count(列名)或 count(常量)来替代 count(*),count(*)是 SQL92 定义的 标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。
说明:count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。
【强制】count(distinct col) 计算该列除 NULL 以外的不重复行数,注意 count(di col1, col2) 若是其中一列全为 NULL,那么即便另外一列有不一样的值,也返回为 0。
【强制】当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为NULL.
【强制】不得使用外键与级联,一切外键概念必须在应用层解决。
【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。
【推荐】in 操做能避免则避免,若实在避免不了,须要仔细评估 in 后边的集合元素数量,控 制在 1000 个以内。
【参考】若是有全球化须要,全部的字符存储与表示,均以 utf-8 编码,注意字符 的区别。
说明: SELECT LENGTH("轻松工做"); 返回为 12 SELECT CHARACTER_LENGTH("轻松工做"); 返回为 4 若是须要存储表情,那么选择 utfmb4 来进行存储,注意它与 -8 编码的区别。
【强制】更新数据表记录时,必须同时更新记录对应的 update_time 字段值为当前时间。
【参考】@Transactional 事务不要滥用。事务会影响数据库的 QPS,另外使用事务的地方需 要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等。
我有一个微信公众号,常常会分享一些Java技术相关的干货;若是你喜欢个人分享,能够用微信搜索“Java团长”或者“javatuanzhang”关注。