阿里巴巴Java开发手册泰山版(整理)//..

阿里巴巴Java开发手册泰山版(整理)

一、编程规约

(一)命名风格

  1. 【强制】代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。

  2. 【强制】常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。

    正例:MAX_STOCK_COUNT / CACHE_EXPIRED_TIME

    反例:MAX_COUNT / EXPIRED_TIME

  3. 【强制】抽象类命名使用 AbstractBase 开头;

    ​ 异常类命名使用Exception结尾;

    ​ 测试类命名以它要测试的类的名称开始,以 Test 结尾

  4. 【强制】POJO 类中的任何布尔类型的变量,都不要加 is前缀,否则部分框架解析会引起序列化错误。

    说明:在本文 MySQL 规约中的建表约定第一条,表达是与否的值采用 is_xxx 的命名方式,所以,需要在 <resultMap>设置从 is_xxx 到 xxx 的映射关系。

    反例:定义为基本数据类型 Boolean isDeleted 的属性,它的方法也是 isDeleted(),框架在反向解析的时

    候,“误以为”对应的属性名称是 deleted,导致属性获取不到,进而抛出异常。

  5. 【强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。

    ​ 包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。

    正例:应用工具类包名为 com.alibaba.ei.kunlun.aap.util、类名为 MessageUtils

    (此规则参考 spring 的框架结构)

  6. 【强制】杜绝完全不规范的缩写,避免望文不知义。

    反例:AbstractClass“缩写”命名成 AbsClass; condition“缩写”命名成 condi,

    此类随意缩写严重降低了代码的可阅读性。

  7. 【推荐】为了达到代码自解释的目标,任何自定义编程元素在命名时,使用尽量完整的单词组合来表达。

    正例:在 JDK 中,对某个对象引用的 volatile 字段进行原子更新的类名为:AtomicReferenceFieldUpdater。

    反例:常见的方法内变量为 int a;的定义方式。

  8. 【推荐】在常量与变量的命名时,表示类型的名词放在词尾,以提升辨识度。

    正例:startTime / workQueue / nameList / TERMINATED_THREAD_COUNT

    反例:startedAt / QueueOfWork / listName / COUNT_TERMINATED_THREAD

  9. 【推荐】如果模块、接口、类、方法使用了设计模式,在命名时需体现出具体模式。

    说明:将设计模式体现在名字中,有利于阅读者快速理解架构设计理念。

    正例: public class OrderFactory;
    public class LoginProxy;
    public class ResourceObserver;

  10. 【推荐】接口类中的方法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁性,并加上有效的Javadoc 注释.

    尽量不要在接口里定义变量,如果一定要定义变量,确定与接口方法相关,并且是整个应用的基础常量。

    正例:接口方法签名 void commit();

    ​接口基础常量 String COMPANY = “alibaba”;

    反例:接口方法定义 public abstract void f();

    说明:JDK8 中接口允许有默认实现,那么这个 default 方法,是对所有实现类都有价值的默认实现。

  11. 接口和实现类的命名有两套规则:

    1)【强制】对于 Service 和 DAO类,基于 SOA 的理念,暴露出来的服务一定是接口,内部的实现类用 Impl 的后缀与接口区别。

    正例:CacheServiceImpl 实现 CacheService 接口。

    2)【推荐】如果是形容能力的接口名称,取对应的形容词为接口名(通常是–able 的形容词)。

    正例:AbstractTranslator 实现 Translatable 接口。

  12. 【参考】枚举类名带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。

    说明:枚举其实就是特殊的常量类,且构造方法被默认强制是私有。

    正例:枚举名字为 ProcessStatusEnum 的成员名称:SUCCESS / UNKNOWN_REASON。

  13. 【参考】各层命名规约:

    A)Service/DAO 层方法命名规约

    1) 获取单个对象的方法用 get 做前缀。

    2) 获取多个对象的方法用 list 做前缀,复数结尾,如:listObjects。

    3) 获取统计值的方法用 count 做前缀。

    4) 插入的方法用 save/insert 做前缀。

    5) 删除的方法用 remove/delete 做前缀。

    6) 修改的方法用 update 做前缀。

    B) 领域模型命名规约

    1) 数据对象:xxxDO,xxx 即为数据表名。

    2) 数据传输对象:xxxDTO,xxx 为业务领域相关的名称。

    3) 展示对象:xxxVO,xxx 一般为网页名称。

    4) POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。



(二)常量定义

  1. 【强制】不允许任何魔法值(即未经预先定义的常量)直接出现在代码中

  2. 【强制】在 long 或者 Long 赋值时,数值后使用大写的 L,不能是小写的 l,小写容易跟数字混淆,造成误解。

  3. 【推荐】不要使用一个常量类维护所有常量,要按常量功能进行归类,分开维护。

    说明:大而全的常量类,杂乱无章,使用查找功能才能定位到修改的常量,不利于理解,也不利于维护。

    正例:缓存相关常量放在类 CacheConsts 下;系统配置相关常量放在类 ConfigConsts 下。

  4. 【推荐】常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量。

    1)跨应用共享常量:放置在二方库中,通常是 client.jar 中的 constant 目录下。
    2)应用内共享常量:放置在一方库中,通常是子模块中的 constant 目录下。

    反例:易懂变量也要统一定义成应用内共享常量,两位工程师在两个类中分别定义了“YES”的变量:
    类 A 中:public static final String YES = “yes”;
    类 B 中:public static final String YES = “y”;
    A.YES.equals(B.YES),预期是 true,但实际返回为 false,导致线上问题。

    ​ 3)子工程内部共享常量:即在当前子工程的 constant 目录下。
    ​ 4)包内共享常量:即在当前包下单独的 constant 目录下。
    ​ 5)类内共享常量:直接在类内部 private static final 定义。

  5. 【推荐】如果变量值仅在一个固定范围内变化用 enum 类型来定义。

    说明:如果存在名称之外的延伸属性应使用 enum 类型,下面正例中的数字就是延伸信息,表示一年中的第几个季节。

    正例:

     public enum SeasonEnum {
          
          
     	SPRING(1), SUMMER(2), AUTUMN(3), WINTER(4);
        
     	private int seq;
     	SeasonEnum(int seq) {
          
          
     		this.seq = seq;
     	}
     	public int getSeq() {
          
          
     		return seq; 
     	}
     }
    


(三)代码格式

  1. 【强制】如果是大括号内为空,则简洁地写成{}即可,大括号中间无需换行和空格;

  2. 【强制】左小括号和右边相邻字符之间不出现空格;右小括号和左边相邻字符之间也不出现空格;而左大括号前需要加空格。

  3. 【强制】任何二目、三目运算符的左右两边都需要加一个空格。

    说明:包括赋值运算符=、逻辑运算符&&、加减乘除符号等。

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

  5. 【强制】采用 4 个空格缩进,禁止使用 tab 字符。

    说明:如果使用 tab 缩进,必须设置 1 个 tab 为 4 个空格。 IDEA 设置 tab 为 4 个空格时,请勿勾选 Use tab

    character;而在 eclipse 中,必须勾选 insert spaces for tabs。

  6. 【强制】注释的双斜线与注释内容之间有且仅有一个空格。

  7. 【强制】在进行类型强制转换时,右括号与强制转换值之间不需要任何空格隔开。

  8. 【强制】单行字符数限制不超过120 个,超出需要换行,换行时遵循如下原则:

    ​ 1)第二行相对第一行缩进 4 个空格,从第三行开始,不再继续缩进,参考示例。

    ​ 2)运算符与下文一起换行。

    ​ 3)方法调用的点符号与下文一起换行。

    ​ 4)方法调用中的多个参数需要换行时,在逗号后进行。

    ​ 5)在括号前不要换行,见反例。

    正例:

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

    反例:

    StringBuilder sb = new StringBuilder();
    // 超过 120 个字符的情况下,不要在括号前换行
    sb.append("you").append("are")...append
    	("lucky");
    
    // 参数很多的方法调用可能超过 120 个字符,逗号后才是换行处
    method(args1, args2, args3, ...
    	, argsX);
    
  9. 【强制】方法参数在定义和传入时,多个参数逗号后边必须加空格。

  10. 【强制】IDE 的 text file encoding 设置为 UTF-8; IDE 中文件的换行符使用 Unix 格式,不要使用 Windows 格式。

  11. 【推荐】单个方法的总行数不超过80 行。

    说明:除注释之外的方法签名、左右大括号、方法内代码、空行、回车及任何不可见字符的总行数不超过80行。

    正例:代码逻辑分清红花和绿叶,个性和共性,绿叶逻辑单独出来成为额外方法,使主干代码更加清晰;共性逻辑抽取成为共性方法,便于复用和维护。

  12. 【推荐】没有必要增加若干空格来使变量的赋值等号与上一行对应位置的等号对齐。

    正例:

    int one = 1;
    long two = 2L;
    float three = 3F;
    StringBuilder sb = new StringBuilder();
    

    说明:增加 sb 这个变量,如果需要对齐,则给 one、two、three 都要增加几个空格,在变量比较多的情

    ​ 况下,是非常累赘的事情。

  13. 【推荐】不同逻辑、不同语义、不同业务的代码之间插入一个空行分隔开来以提升可读性。

    说明:任何情形,没有必要插入多个空行进行隔开。



(四)OOP 规约 2021.10.28

  1. 【强制】避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。

  2. 【强制】所有的覆写方法,必须加 @Override 注解。

    说明:getObject()与get0bject()的问题。一个是字母的O,一个是数字的0,加@Override可以准确判断是否覆盖成功。另外,如果在抽象类中对方法签名进行修改,其实现类会马上编译报错。

  3. 【强制】相同参数类型,相同业务含义,才可以使用Java的可变参数,避免使用 Object。

    说明:可变参数必须放置在参数列表的最后。(提倡同学们尽量不用可变参数编程)
    正例:public List listUsers(String type, Long… ids) {…}

  4. 【强制】外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@Deprecated注解,并清晰地说明采用的新接口或者新服务是什么。

  5. 【强制】不能使用过时的类或方法。

    说明:java.net.URLDecoder 中的方法decode(String encodeStr) 这个方法已经过时,应该使用双参数decode(String source, String encode)。
    接口提供方既然明确是过时接口,那么有义务同时提供新的接口;
    作为调用方来说,有义务去考证过时方法的新实现是什么

  6. 【强制】Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。

    正例:“test”.equals(object);
    反例:object.equals(“test”);
    说明:推荐使用java.util.Objects#equals(JDK7引入的工具类)。

  7. 【强制】所有整型包装类对象之间值的比较,全部使用equals 方法比较。

    说明:对于Integer var = ? 在-128至127之间的赋值,Integer对象是在 IntegerCache.cache产生,会复用已有对象,这个区间内的Integer值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用equals方法进行判断。

  8. 【强制】任何货币金额,均以最小货币单位且整型类型来进行存储。

  9. 【强制】浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用equals来判断。

    说明:浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。二进制无法精确表示大部分的十进制小数,具体原理参考《码出高效》。

    反例:

    float a = 1.0f - 0.9f;
    float b = 0.9f - 0.8f;
    if (a == b) {
          
          
    // 预期进入此代码快,执行其它业务逻辑
    // 但事实上a==b的结果为false
    }
    Float x = Float.valueOf(a);
    Float y = Float.valueOf(b);
    if (x.equals(y)) {
          
          
    // 预期进入此代码快,执行其它业务逻辑
    // 但事实上equals的结果为false
    }
    

    正例:
    (1) 指定一个误差范围,两个浮点数的差值在此范围之内,则认为是相等的。

    float a = 1.0f - 0.9f;
    float b = 0.9f - 0.8f;
    float diff = 1e-6f;
    if (Math.abs(a - b) < diff) {
          
          
    System.out.println("true");
    }
    

    (2) 使用BigDecimal来定义值,再进行浮点数的运算操作。

    BigDecimal a = new BigDecimal("1.0");
    BigDecimal b = new BigDecimal("0.9");
    BigDecimal c = new BigDecimal("0.8");
    BigDecimal x = a.subtract(b);
    BigDecimal y = b.subtract(c);
    if (x.equals(y)) {
          
          
    System.out.println("true");
    }
    
    
    
    

附2: 专有名词解释 2021.10.25

  1. CAS(Compare And Swap)

    阿里巴巴专指数据库表一一对应的POJO类
    解决多线程并行情况下使用锁造成性能损耗的一种机制,这是硬件实现的原子操作。
    CAS操作包含三个操作数:内存位置、预期原值和新值。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。

  2. DO(Data Object)

    阿里巴巴专指数据库表一一对应的POJO类

  3. GAV(GroupId、ArtifactId、Version)

    Maven坐标,是用来唯一标识jar包。

  4. AQS(AbstractQueuedSynchronizer)

    利用先进先出队列实现的底层同步工具类,它是很多上层同步实现类的基础,比如:ReentrantLock、CountDownLatch、Semaphore等,它们通过继承AQS实现其模版方法,然后将AQS子类作为同步组件的内部类,通常命名为Sync。

  5. ORM(Object Relation Mapping)

    对象关系映射,对象领域模型与底层数据之间的转换,本文泛指iBATIS, mybatis等框架。

  6. POJO(Plain Ordinary Java Object):

    在本规约中,POJO专指只有setter/getter/toString的简单类,包括DO/DTO/BO/VO等。

  7. AO(Application Object):

    阿里巴巴专指Application Object,即在Service层上,极为贴近业务的复用代码。

  8. NPE(java.lang.NullPointerException):

    空指针异常。

  9. OOM(Out Of Memory):

    源于 java.lang.OutOfMemoryError,当 JVM 没有足够的内存来为对象分配空间并且垃圾回收器也无法回收空间时,系统出现的严重状况。

  10. 一方库:

    本工程内部子项目模块依赖的库(jar 包)。

  11. 二方库:

    公司内部发布到中央仓库,可供公司内部其它应用依赖的库(jar 包)。

  12. 三方库:

    公司之外的开源库(jar 包)。



附3: 错误码列表 2021.10.28

错误码 中文描述 说明
00000 一切ok 正确执行后的返回
A0001 用户端错误 一级宏观错误码
A0100 用户注册错误 二级宏观错误码
A0101 用户未同意隐私协议
A0102 注册国家或地区受限
A0110 用户名校验失败
A0111 用户名已存在
A0112 用户名包含敏感词
A0113 用户名包含特殊字符
A0120 密码校验失败
A0121 密码长度不够
A0122 密码强度不够
A0130 校验码输入错误
A0131 短信校验码输入错误
A0132 邮件校验码输入错误
A0133 语音校验码输入错误
A0140 用户证件异常
A0141 用户证件类型未选择
A0142 大陆身份证编号校验非法
A0143 护照编号校验非法
A0144 军官证编号校验非法
A0150 用户基本信息校验失败
A0151 手机格式校验失败
A0152 地址格式校验失败
A0153 邮箱格式校验失败
A0200 用户登陆异常 二级宏观错误码
A0201 用户账户不存在
A0202 用户账户被冻结
A0203 用户账户已作废
A0210 用户密码错误
A0211 用户输入密码次数超限
A0220 用户身份校验失败
A0221 用户指纹识别失败
A0222 用户面容识别失败
A0223 用户未获得第三方登陆授权
A0230 用户登陆已过期
A0240 用户验证码错误
A0241 用户验证码尝试次数超限
A0300 访问权限异常 二级宏观错误码
A0301 访问未授权
A0302 正在授权中
A0303 用户授权申请被拒绝
A0310 因访问对象隐私设置被拦截
A0311 授权已过期
A0312 无权限使用API
A0320 用户访问被拦截
A0321 黑名单用户
A0322 账号被冻结
A0323 非法IP地址
A0324 网关访问受限
A0325 地域黑名单
A0330 服务已欠费
A0340 用户签名异常
A0341 RSA签名错误
A0400 用户请求参数错误 二级宏观错误码
A0401 包含非法恶意跳转链接
A0402 无效的用户输入
A0410 请求必填参数为空
A0411 用户订单号为空
A0412 订购数量为空
A0413 缺少时间戳参数
A0414 非法的时间戳参数
A0420 请求参数值超出允许的范围
A0421 参数格式不匹配
A0422 地址不在服务范围
A0423 时间不在服务范围
A0424 金额超出限制
A0425 数量超出限制
A0426 请求批量处理总个数超出限制
A0427 请求JSON解析失败
A0430 用户输入内容非法
A0431 包含违禁敏感词
A0432 图片包含违禁信息
A0433 文件侵犯版权
A0440 用户操作异常
A0441 用户支付超时
A0442 确认订单超时
A0443 订单已关闭
A0500 用户请求服务异常 二级宏观错误码
A0501 请求次数超出限制
A0502 请求并发数超出限制
A0503 用户操作请等待
A0504 WebSocket连接异常
A0505 WebSocket连接断开
A0506 用户重复请求
A0600 用户资源异常 二级宏观错误码
A0601 账户余额不足
A0602 用户磁盘空间不足
A0603 用户内存空间不足
A0604 用户OSS容量不足
A0605 用户配额已用光 蚂蚁森林浇水数或每天抽奖数
A0700 用户上传文件异常 二级宏观错误码
A0701 用户上传文件类型不匹配
A0702 用户上传文件太大
A0703 用户上传图片太大
A0704 用户上传视频太大
A0705 用户上传压缩文件太大
A0800 用户当前版本异常 二级宏观错误码
A0801 用户安装版本与系统不匹配
A0802 用户安装版本过低
A0803 用户安装版本过高
A0804 用户安装版本已过期
A0805 用户API请求版本不匹配
A0806 用户API请求版本过高
A0807 用户API请求版本过低
A0900 用户隐私未授权 二级宏观错误码
A0901 用户隐私未签署
A0902 用户摄像头未授权
A0903 用户相机未授权
A0904 用户图片库未授权
A0905 用户文件未授权
A0906 用户位置信息未授权
A0907 用户通讯录未授权
A1000 用户设备异常 二级宏观错误码
A1001 用户相机异常
A1002 用户麦克风异常
A1003 用户听筒异常
A1004 用户扬声器异常
A1005 用户GPS定位异常
B0001 系统执行出错 一级宏观错误码
B0100 系统执行超时 二级宏观错误码
B0101 系统订单处理超时
B0200 系统容灾功能被触发 二级宏观错误码
B0210 系统限流
B0220 系统功能降级
B0300 系统资源异常 二级宏观错误码
B0310 系统资源耗尽
B0311 系统磁盘空间耗尽
B0312 系统内存耗尽
B0313 文件句柄耗尽
B0314 系统连接池耗尽
B0315 系统线程池耗尽
B0320 系统资源访问异常
B0321 系统读取磁盘文件失败
C0001 调用第三方服务出错 一级宏观错误码
C0100 中间件服务出错 二级宏观错误码
C0110 RPC服务出错
C0111 RPC服务未找到
C0112 RPC服务未注册
C0113 接口不存在
C0120 消息服务出错
C0121 消息投递出错
C0122 消息消费出错
C0123 消息订阅出错
C0124 消息分组未查到
C0130 缓存服务出错
C0131 key长度超过限制
C0132 value长度超过限制
C0133 存储容量已满
C0134 不支持的数据格式
C0140 配置服务出错
C0150 网络资源服务出错
C0151 VPN服务出错
C0152 CDN服务出错
C0153 域名解析服务出错
C0154 网关服务出错
C0200 第三方系统执行超时 二级宏观错误码
C0210 RPC执行超时
C0220 消息投递超时
C0230 缓存服务超时
C0240 配置服务超时
C0250 数据库服务超时
C0300 数据库服务出错 二级宏观错误码
C0311 表不存在
C0312 列不存在
C0321 多表关联中存在多个相同名称的列
C0331 数据库死锁
C0341 主键冲突
C0400 第三方容灾系统被触发 二级宏观错误码
C0401 第三方系统限流
C0402 第三方功能降级
C0500 通知服务出错 二级宏观错误码
C0501 短信提醒服务失败
C0502 语音提醒服务失败
C0503 邮件提醒服务失败


持续更新

猜你喜欢

转载自blog.csdn.net/weixin_46644403/article/details/120413622