java编码规范(参考阿里巴巴开发手册)

对阿里巴巴java开发手册中所有的强制内容进行了整理

一、编程规约

1、命名风格

  1. 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。
  2. 代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
  3. 类名使用 UpperCamelCase 风格,必须遵从驼峰形式,但以下情形例外: DO / BO / DTO / VO / AO
  4. 方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从驼峰形式。
  5. 常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
  6. 抽象类命名使用 Abstract 或 Base 开头 ; 异常类命名使用 Exception 结尾 ; 测试类命名以它要测试的类的名称开始,以 Test 结尾。
  7. 中括号是数组类型的一部分,数组定义如下: String[] args;
  8. POJO 类中布尔类型的变量,都不要加 is ,否则部分框架解析会引起序列化错误。
  9. 包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。
  10. 杜绝完全不规范的缩写,避免望文不知义。

2、常量定义

  1. 不允许任何魔法值 ( 即未经定义的常量 ) 直接出现在代码中。
  2. long 或者 Long 初始赋值时,使用大写的 L ,不能是小写的 l ,小写容易跟数字 1 混淆,造成误解。

3、代码格式

  1. 大括号的使用约定。如果是大括号内为空,则简洁地写成{}即可,不需要换行 ; 如果是非空代码块则:
    1 ) 左大括号前不换行。
    2 ) 左大括号后换行。
    3 ) 右大括号前换行。
    4 ) 右大括号后还有 else 等代码则不换行 ; 表示终止的右大括号后必须换行。
  2. 左小括号和字符之间不出现空格 ; 同样,右小括号和字符之间也不出现空格。详见第 5 条下方正例提示。
  3. if / for / while / switch / do 等保留字与括号之间都必须加空格。
  4. 任何二目、三目运算符的左右两边都需要加一个空格。
  5. 采用 4 个空格缩进,禁止使用 tab 字符
  6. 注释的双斜线与注释内容之间有且仅有一个空格。
  7. 单行字符数限制不超过 120 个,超出需要换行,换行时遵循如下原则:
    1) 第二行相对第一行缩进 4 个空格,从第三行开始,不再继续缩进,参考示例。
    2 ) 运算符与下文一起换行。
    3 ) 方法调用的点符号与下文一起换行。
    4 ) 方法调用时,多个参数,需要换行时,在逗号后进行。
    5 ) 在括号前不要换行,见反例。
  8. 方法参数在定义和传入时,多个参数逗号后边必须加空格。
  9. IDE 的 text file encoding 设置为 UTF -8 ; IDE 中文件的换行符使用 Unix 格式,不要使用 Windows 格式。

1、OOP规约

  1. 避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。
  2. 所有的覆写方法,必须加@ Override 注解。
  3. 相同参数类型,相同业务含义,才可以使用 Java 的可变参数,避免使用 Object 。
  4. 外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@ Deprecated 注解,并清晰地说明采用的新接口或者新服务是什么。
  5. 不能使用过时的类或方法。
  6. Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals 。
  7. 所有的相同类型的包装类对象之间值的比较,全部使用 equals 方法比较。
  8. 关于基本数据类型与包装数据类型的使用标准如下:
    1 ) 【强制】所有的 POJO 类属性必须使用包装数据类型。
    2 ) 【强制】 RPC 方法的返回值和参数必须使用包装数据类型。
  9. 定义 DO / DTO / VO 等 POJO 类时,不要设定任何属性默认值。
  10. 序列化类新增属性时,请不要修改 serialVersionUID 字段,避免反序列失败 ; 如果完全不兼容升级,避免反序列化混乱,那么请修改 serialVersionUID 值。
  11. 构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中。
  12. POJO 类必须写 toString 方法。使用 IDE 的中工具: source > generate toString时,如果继承了另一个 POJO 类,注意在前面加一下 super . toString 。

5、集合处理

  1. 关于 hashCode 和 equals 的处理,遵循如下规则:
    1) 只要重写 equals ,就必须重写 hashCode 。
    2) 因为 Set 存储的是不重复的对象,依据 hashCode 和 equals 进行判断,所以 Set 存储的
    对象必须重写这两个方法。
    3) 如果自定义对象做为 Map 的键,那么必须重写 hashCode 和 equals 。
  2. ArrayList 的 subList 结果不可强转成 ArrayList ,否则会抛出 ClassCastException异常,即 java . util . RandomAccessSubList cannot be cast to java . util . ArrayList .
  3. 在 subList 场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、删除均会产生 ConcurrentModificationException 异常
  4. 使用集合转数组的方法,必须使用集合的 toArray(T[] array) ,传入的是类型完全一样的数组,大小就是 list . size()
  5. 使用工具类 Arrays . asList() 把数组转换成集合时,不能使用其修改集合相关的方法,它的 add / remove / clear 方法会抛出 UnsupportedOperationException 异常
  6. 泛型通配符<? extends T >来接收返回的数据,此写法的泛型集合不能使用 add 方法,而 <? super T> 不能使用 get 方法,做为接口调用赋值时易出错。
  7. 不要在 foreach 循环里进行元素的 remove / add 操作。 remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁
  8. 在 JDK 7 版本及以上, Comparator 要满足如下三个条件,不然 Arrays . sort ,Collections . sort 会报 IllegalArgumentException 异常。

6、并发处理

  1. 获取单例对象需要保证线程安全,其中的方法也要保证线程安全。
  2. 创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。
  3. 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
  4. 线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
  5. SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为static ,必须加锁,或者使用 DateUtils 工具类。
  6. 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁 ; 能锁区块,就不要锁整个方法体 ; 能用对象锁,就不要用类锁。
  7. 对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。
  8. 并发修改同一记录时,避免更新丢失,需要加锁。要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用 version 作为更新依据。
  9. 多线程并行处理定时任务时, Timer 运行多个 TimeTask 时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用 ScheduledExecutorService 则没有这个问题。

7、控制语句

  1. 在一个 switch 块内,每个 case 要么通过 break / return 等来终止,要么注释说明程序将继续执行到哪一个 case 为止 ; 在一个 switch 块内,都必须包含一个 default 语句并且放在最后,即使它什么代码也没有。
  2. 在 if / else / for / while / do 语句中必须使用大括号。即使只有一行代码,避免采用单行的编码方式: if (condition) statements

8、注释规约

  1. 类、类属性、类方法的注释必须使用 Javadoc 规范,使用/*内容/格式,不得使用// xxx 方式。
  2. 所有的抽象方法 ( 包括接口中的方法 ) 必须要用 Javadoc 注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。
  3. 所有的类都必须添加创建者和创建日期。
  4. 方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使用/* */注释,注意与代码对齐。
  5. 所有的枚举类型字段必须要有注释,说明每个数据项的用途。

9、其他

  1. 在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。
  2. velocity 调用 POJO 类的属性时,建议直接使用属性名取值即可,模板引擎会自动按规范调用 POJO 的 getXxx() ,如果是 boolean 基本数据类型变量 (boolean 命名不需要加 is前缀 ) ,会自动调用 isXxx() 方法。
  3. 后台输送给页面的变量必须加 $!{var} ——中间的感叹号。
  4. 注意 Math . random() 这个方法返回是 double 类型,注意取值的范围 0≤ x <1 ( 能够取到零值,注意除零异常 ) ,如果想获取整数类型的随机数,不要将 x 放大 10 的若干倍然后取整,直接使用 Random 对象的 nextInt 或者 nextLong 方法。
  5. 获取当前毫秒数 System . currentTimeMillis(); 而不是 new Date() . getTime();

二、异常日志

1、异常处理

  1. Java 类库中定义的一类 RuntimeException 可以通过预先检查进行规避,而不应该通过 catch 来处理,比如: IndexOutOfBoundsException , NullPointerException 等等。
  2. 异常不要用来做流程控制,条件控制,因为异常的处理效率比条件分支低。
  3. 对大段代码进行 try - catch ,这是不负责任的表现。 catch 时请分清稳定代码和非稳定代码,稳定代码指的是无论如何不会出错的代码。对于非稳定代码的 catch 尽可能进行区分异常类型,再做对应的异常处理。
  4. 捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容。
  5. 有 try 块放到了事务代码中, catch 异常后,如果需要回滚事务,一定要注意手动回滚事务。
  6. finally 块必须对资源对象、流对象进行关闭,有异常也要做 try - catch 。
  7. 不能在 finally 块中使用 return , finally 块中的 return 返回后方法结束执行,不会再执行 try 块中的 return 语句。
  8. 捕获异常与抛异常,必须是完全匹配,或者捕获异常是抛异常的父类。

2、日志规约

  1. 应用中不可直接使用日志系统 (Log 4 j 、 Logback) 中的 API ,而应依赖使用日志框架SLF 4 J 中的 API ,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
  2. 日志文件推荐至少保存 15 天,因为有些异常具备以“周”为频次发生的特点。
  3. 应用中的扩展日志 ( 如打点、临时监控、访问日志等 ) 命名方式:
    appName _ logType _ logName . log 。 logType :日志类型,推荐分类有
    stats / desc / monitor / visit 等 ;logName :日志描述。这种命名的好处:通过文件名就可知道日志文件属于什么应用,什么类型,什么目的,也有利于归类查找。
  4. 对 trace / debug / info 级别的日志输出,必须使用条件输出形式或者使用占位符的方式。
  5. 避免重复打印日志,浪费磁盘空间,务必在 log 4 j . xml 中设置 additivity = false 。
  6. 异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么通过关键字 throws 往上抛出。

三、单元测试

  1. 好的单元测试必须遵守 AIR 原则。
  2. 单元测试应该是全自动执行的,并且非交互式的。测试框架通常是定期执行的,执行过程必须完全自动化才有意义。输出结果需要人工检查的测试不是一个好的单元测试。单元测试中不准使用 System.out 来进行人肉验证,必须使用 assert 来验证。
  3. 保持单元测试的独立性。为了保证单元测试稳定可靠且便于维护,单元测试用例之间决不能互相调用,也不能依赖执行的先后次序。
  4. 单元测试是可以重复执行的,不能受到外界环境的影响。
  5. 对于单元测试,要保证测试粒度足够小,有助于精确定位问题。单测粒度至多是类级别,一般是方法级别。
  6. 核心业务、核心应用、核心模块的增量代码确保单元测试通过。
  7. 单元测试代码必须写在如下工程目录: src/test/java ,不允许写在业务代码目录下。

四、安全规约

  1. 隶属于用户个人的页面或者功能必须进行权限控制校验。
  2. 用户敏感数据禁止直接展示,必须对展示数据进行脱敏。
  3. 用户输入的 SQL 参数严格使用参数绑定或者 METADATA 字段值限定,防止 SQL 注入,禁止字符串拼接 SQL 访问数据库。
  4. 用户请求传入的任何参数必须做有效性验证。
  5. 禁止向 HTML 页面输出未经安全过滤或未正确转义的用户数据。
  6. 表单、 AJAX 提交必须执行 CSRF 安全过滤。
  7. 在使用平台资源,譬如短信、邮件、电话、下单、支付,必须实现正确的防重放限制,如数量限制、疲劳度控制、验证码校验,避免被滥刷、资损。

五、MySQL数据库

1、建表规约

  1. 表达是与否概念的字段,必须使用 is _ xxx 的方式命名,数据类型是 unsigned tinyint( 1 表示是,0 表示否 ) 。
  2. 表名、字段名必须使用小写字母或数字 , 禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。
  3. 表名不使用复数名词。
  4. 禁用保留字,如 desc 、 range 、 match 、 delayed 等,请参考 MySQL 官方保留字。
  5. 主键索引名为 pk_ 字段名;唯一索引名为 uk _字段名 ; 普通索引名则为 idx _字段名。
  6. 小数类型为 decimal ,禁止使用 float 和 double 。
  7. 如果存储的字符串长度几乎相等,使用 char 定长字符串类型。
  8. varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长度大于此值,定义字段类型为 text ,独立出来一张表,用主键来对应,避免影响其它字段索引效率。
  9. 表必备三字段: id , gmt _ create , gmt _ modified 。

2、索引规约

  1. 业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。
  2. 超过三个表禁止 join 。需要 join 的字段,数据类型必须绝对一致 ; 多表关联查询时,保证被关联的字段需要有索引。
  3. 在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。
  4. 页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。

3、SQL语句

  1. 不要使用 count( 列名 ) 或 count( 常量 ) 来替代 count( * ) , count( * ) 是 SQL 92 定义的标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。
  2. count(distinct col) 计算该列除 NULL 之外的不重复行数,注意 count(distinctcol 1, col 2 ) 如果其中一列全为 NULL ,那么即使另一列有不同的值,也返回为 0。
  3. 当某一列的值全是 NULL 时, count(col) 的返回结果为 0,但 sum(col) 的返回结果为NULL ,因此使用 sum() 时需注意 NPE 问题。
  4. 使用 ISNULL() 来判断是否为 NULL 值。
  5. 在代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句。
  6. 不得使用外键与级联,一切外键概念必须在应用层解决。
  7. 禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。
  8. 数据订正时,删除和修改记录时,要先 select ,避免出现误删除,确认无误才能执行更新语句。

4、ORM映射

  1. 在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明。
  2. POJO 类的 布尔 属性不能加 is ,而数据库字段必须加 is _,要求在 resultMap 中进行字段与属性之间的映射。
  3. 不要用 resultClass 当返回参数,即使所有类属性名与数据库字段一一对应,也需要定义 ; 反过来,每一个表也必然有一个与之对应。
  4. sql. xml 配置参数使用:#{},# param # 不要使用${} 此种方式容易出现 SQL 注入。
  5. iBATIS 自带的 queryForList(String statementName , int start , int size) 不推荐使用。
  6. 不允许直接拿 HashMap 与 Hashtable 作为查询结果集的输出。
  7. 更新数据表记录时,必须同时更新记录对应的 gmt _ modified 字段值为当前时间。

六、工程结构

1、二方库依赖

  1. 定义 GAV 遵从以下规则:
    1 ) GroupID 格式: com .{公司/ BU }.业务线. [ 子业务线 ] ,最多 4 级。
    说明:{公司/ BU } 例如: alibaba / taobao / tmall / aliexpress 等 BU 一级 ; 子业务线可选。
    正例: com . taobao . jstorm 或 com.alibaba.dubbo.register
    2 ) ArtifactID 格式:产品线名-模块名。语义不重复不遗漏,先到中央仓库去查证一下。
    正例: dubbo - client / fastjson - api / jstorm - tool
    3 ) Version :详细规定参考下方。

  2. 二方库版本号命名方式:主版本号.次版本号.修订号
    1 ) 主版本号 主版本号:产品方向改变,或者大规模 API 不兼容,或者架构不兼容升级。
    2 ) 次版本号 次版本号:保持相对兼容性,增加主要功能特性,影响范围极小的 API 不兼容修改。
    3 ) 修订号 修订号:保持完全兼容性,修复 BUG 、新增次要功能特性等。

  3. 线上应用不要依赖 SNAPSHOT 版本 ( 安全包除外 )。

  4. 二方库的新增或升级,保持除功能点之外的其它 jar 包仲裁结果不变。如果有改变,必须明确评估和验证,建议进行 dependency : resolve 前后信息比对,如果仲裁结果完全不一致,那么通过 dependency : tree 命令,找出差异点,进行< excludes >排除 jar 包。

  5. 二方库里可以定义枚举类型,参数可以使用枚举类型,但是接口返回值不允许使用枚举类型或者包含枚举类型的 POJO 对象。

  6. 依赖于一个二方库群时,必须定义一个统一的版本变量,避免版本号不一致。

  7. 禁止在子项目的 pom 依赖中出现相同的 GroupId ,相同的 ArtifactId ,但是不同的Version 。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值