java规范阿⾥巴巴_阿⾥巴巴Java代码规范
1. 抽象类命名使⽤ Abstratc开头。
2. 阿⾥强制规定不允许任何魔法值(未经定义的常量)直接出现在代码中。魔法值会让代码的可读性⼤⼤降低,⽽且如果同样的数值多次出现时,容易出现不清楚这些数值是否代表同样的
含义。另⼀⽅⾯,如果本来应该使⽤相同的数值,⼀旦⽤错,也难以发现。因此可以采⽤以下两点,极⼒避免使⽤魔法数值。
3. 阿⾥推荐如果变量值仅在⼀个范围内变化,且带有名称之外的延伸属性,定义为枚举类。对于固定并且编译时对象,如 Status、Type 等,应该采⽤ enum ⽽⾮⾃定义常量实现,enum 的
好处是类型更清楚,不会再编译时混淆。这是⼀个建议性的试⽤推荐,枚举可以让开发者在 IDE 下使⽤更⽅便,也更安全。另外就是枚举类型是⼀种具有特殊约束的类类型,这些约束的
存在使得枚举类本⾝更加简洁、安全、便捷。
4. 阿⾥强制规定如果是⼤括号为空,则简洁地写成{}即可,不需要换⾏
5. 阿⾥强制规定单⾏字符数限制不超过 120 个,超出需要换⾏,换⾏时遵循如下原则:
1).第⼆⾏相对第⼀⾏缩进 4 个空格,从第三⾏开始,不再继续缩进,参考⽰例。
2).运算符与下⽂⼀起换⾏。
3).⽅法调⽤的点符号与下⽂⼀起换⾏。
4).⽅法调⽤时,多个参数,需要换⾏时,在逗号后进⾏。
5).在括号前不要换⾏
6. 阿⾥强制规定代码中避免通过⼀个类的对象引⽤访问此类的静态变量或静态⽅法,暂时⽆谓增加编译器解析成本,直接⽤类名来访问即可。
为什么需要这样做呢?因为被 static 修饰过的变量或者⽅法都是随着类的初始化产⽣的,在堆内存中有⼀块专门的区域⽤来存放,后续直接⽤类名访问即可,避免编译成本的增加和实例
对象存放空间的浪费。
StackOverflow 上也有⼈提出了相同的疑问,⽹友较为精辟的回复是"这是由于⽣命周期决定的,静态⽅法或者静态变量不是以实例为基准的,⽽是以类为基准,所以直接⽤类访问,否则
违背了设计初衷"。那为什么还保留了实例的访问⽅式呢?可能是因为允许应⽤⽅⽆污染修改吧。
7. 阿⾥强制规定相同参数类型、相同业务类型,才可以使⽤ Java 的可变参数,避免使⽤ Object,并且要求可变参数必须放置在参数列表的最后(提倡同学们尽量不⽤可变参数编程)。
拥有可变参数的⽅法可以被重载,在被调⽤时,如果能匹配到参数定长的⽅法则优先调⽤参数定长的⽅法。
8.单例模式:
1).双检查锁机制(Double Check Locking),这⾥在声明变量时使⽤了 volatile 关键字来保证其线程间的可见性;在同步代码块中使⽤⼆次检查,以保证其不被重复实例化。
集合其⼆者,这种实现⽅式既保证了其⾼效性,也保证了其线程安全性。
2).懒汉式:
9. 阿⾥强制规定在⼀个 switch 块内,每个 case 要么通过 break/return 等来终⽌,要么注释说明程序将继续执⾏到哪⼀个 case 为⽌;在⼀个 switch 块内,都必须包含⼀个 default
语句并且放在最后,即使它什么代码也没有。语法上来说,default 语句中的 break 是多余的,但是如果后续添加额外的 case,可以避免不到匹配 case 项的错误。
10. 阿⾥强制规定使⽤集合转数组的⽅法,必须使⽤集合的 toArray(T[] arrays),传⼊的是类型完全⼀样的数组,⼤⼩就是 list.size()。使⽤ toArray 带参⽅法,⼊参分配的数组空间不够⼤时,
toArray ⽅法内部将重新分配内存空间,并返回新数组地址;如果数组元素⼤于实际所需,下标为[list.size()]的数组元素将被置为 null,其它数组元素保持原值,因此最好将⽅法⼊参数组⼤⼩定义与集合元素个数⼀致。
String[] array = new String[list.size()];
array = Array(array);
11. 阿⾥强制要求⽅法内部单⾏注释,在被注释语句上⽅另起⼀⾏,使⽤//注释。⽅法内部多⾏注释使⽤/**/注释,注意与代码对照。
百度规定⽅法注释采⽤标准的 Javadoc 注释规范,注释中必须提供⽅法说明、参数说明及返回值和异常说明。腾讯规定采⽤ JavaDoc ⽂档注释,在⽅法定义之前应该对其进⾏注释,
包括⽅法的描述、输⼊、输出以及返回值说明、抛出异常说明、参考链接等。
12. 不带参数的 toArray()构造⼀个 Object 数组,然后进⾏数据拷贝
13. 阿⾥推荐任何数据结构的构造或初始化,都应指定⼤⼩,避免数据结构暂时⽆限增长吃光内存。
⾸先明确⼀点,阿⾥这⾥指的⼤⼩具体是指数据结构的最⼤长度。⼤部分 Java 集合类在构造时指定的⼤⼩都是初始尺⼨(initial Capacity),⽽不是尺⼨上限(Capacity),只有⼏
种队列除外,例如 ArrayBlockingQueue、LinkedBlockingQueue,它们在构造时可以指定队列的最⼤长度。阿⾥推荐的⽬的是为了合理规划内存,避免出现 OOM(Out of Memory)异常。java类的概念
14. 阿⾥强制规定 Java 类库中的 RuntimeException 可以通过预先检查进⾏规避,⽽不应该通过 catch 来处理,例如IndexOutOfBoundsException、NullPointerException 等。
RuntimeException,也被称为运⾏时异常,通常是由于代码中的 bug 引起的,正确的处理⽅式是去检查代码,通过添加数据长度判断,判断对象是否为空等⽅法区规避,⽽不是靠捕获来规避这种异常。
15. 阿⾥强制规定有 try 块放到了事务代码中,catch 异常后,如果需要回滚事务,⼀定要注意⼿动回滚事务。
try catch 代码块中对异常的处理,可能会遗漏事务的⼀致性,当事务控制不使⽤其他框架管理时,事务需要⼿动回滚。实际使⽤如果引⼊第三⽅的框架对事务进⾏管理,⽐如 Spring,则根据第三⽅
框架的实际实现情况,确定是否有必要⼿动回滚。当第三⽅事务管理框架本⾝就会对于异常进⾏抛出时需要做事务回滚。例如 Spring 在
@Transactional 的 annotation 注解下,会默认开启运⾏时异常事务回滚。
16. 阿⾥强制规定应⽤中不可直接使⽤⽇志系统(Log4j、Logback)中的 API,⽽应依赖使⽤⽇志框架 SLF4J 中的 API,使⽤门⾯模式的⽇志框架,有利于维护和各个类的⽇志处理⽅式统⼀。
17. 阿⾥强制规定⽇志⽂件⾄少保存 15 天,因为有些异常具备以"周"为频次发⽣的特点。
⽇志保留时间推荐 15 天以上,但是保留时间也不宜过长,⼀般不超过 21 天,否则造成硬盘空间的浪费。对于⼀些长周期性执⾏的逻辑,可以根据实际情况调整该保存时间,同时也
需要保证⽇志能够监控到关键的应⽤。
对于长周期执⾏的逻辑,可以使⽤特定的 appender,并使⽤不同的⽇志清理规则,如时间、⼤⼩等。如⼀⽉执⾏⼀次的定时任务,可以将⽇志输出到新的⽇志⽂件,然后通过⼤⼩限定
的规则进⾏清理,并不⼀定要使⽤时间清理的逻辑。
18. 阿⾥强制要求对于⾪属于⽤户个⼈的页⾯或者功能必须进⾏权限控制校验。
涉及到对于数据的增删改查,必须有权限的控制和校验,要有⼀个⿊⽩名单的控制,不能依赖于前台页⾯的简单控制,后台要有对于完整的权限控制的实现。这样就能尽可能地防治数据的错误修改。
19. 阿⾥强制要求⽤户请求传⼊的任何参数必须做有效校验。
20.单元测试:
1). 单元测试应该⾃动执⾏:阿⾥强制单元测试应该是全⾃动执⾏的,并且⾮交互式的。测试框架通常是定期执⾏的,执⾏过程必须完全⾃动化才有意义。输出结果需要⼈⼯检查的测试
不是⼀个号的单元测试。单元测试中不准使⽤ System.out 来进⾏⼈⾁验证,必须使⽤ assert 来验证。
2). 单元测试应该是独⽴的:阿⾥强制保持单元测试的独⽴性。为了保证单元测试稳定可靠且便于维护,单元测试⽤例之间决不能互相调⽤,也不能依赖执⾏的先后次序。反例:method2
需要依赖 method1 的执⾏,将执⾏结果作为 method2 的输⼊。
编写单元测试时遇到的这类依赖可以使⽤ mock 来模拟输⼊和期望的返回,这样所以来的⽅法内部逻辑的变更就不会影响到外部的实现。
3).阿⾥推荐编写单元测试代码遵守 BCDE 原则,以保证被测试模块的交付质量。
a). B(Border):确保参数边界值均被覆盖。例如:对于数字,测试负数、0、正数、最⼩值、最⼤值、NaN(⾮数字)、⽆穷⼤值等。对于字符串,测试空字符串、单字符、
⾮ ASCII 字符串、多字节字符串等。对于集合类型,测试空、第⼀个元素、最后⼀个元素等。对于⽇期,测试 1 ⽉ 1 ⽇、2 ⽉ 29 ⽇、12 ⽉ 31 ⽇等。被测试的类本⾝
也会暗⽰⼀些特定情况下的边界值。对于边界情况的测试⼀定要详尽。
b). C(Connect):确保输⼊和输出的正确关联性。例如,测试某个时间判断的⽅法 boolean inTimeZone(Long timeStamp),该⽅法根据输⼊的时间戳判断该事件是否存在于某个
时间段内,返回 boolean 类型。如果测试输⼊的测试数据为 Long 类型的时间戳,对于输出的判断应该是对于 boolean 类型的处理。如果测试输⼊的测试数据为⾮ Long 类型
数据,对于输出的判断应该是报错信息是否正确。
c).D(Design):任务程序的开发包括单元测试都应该遵循设计⽂档。
d).E(Error):单元测试包括对各种⽅法的异常测试,测试程序对异常的响应能⼒。
21.《单元测试之道(Java 版)》这本书⾥⾯提到了关于边界测试的 CORRECT 原则:
1).⼀致性(Conformance):值是否符合预期格式(正常的数据),列出所有可能不⼀致的数据,进⾏验证。
2).有序性(Ordering):传⼊的参数的顺序不同的结果是否正确,对排序算法会产⽣影响,或者是对类的属性赋值顺序不同会不会产⽣错误。
3).区间性(Range):参数的取值范围是否在某个合理的区间范围内。
4).引⽤/耦合性(Reference):程序依赖外部的⼀些条件是否已满⾜。前置条件:系统必须处于什么状态下,该⽅法才能运⾏。后置条件,你的⽅法将会保证哪些状态发⽣改变。
5).存在性(Existence):参数是否真的存在,引⽤为 Null,String 为空,数值为 0 或者物理介质不存在时,程序是否能正常运⾏。
6).基数性(Cardinality):考虑以"0-1-N 原则",当数值分别为 0、1、N 时,可能出现的结果,其中 N 为最⼤值。
7).时间性(Time):相对时间指的是函数执⾏的依赖顺序,绝对时间指的是超时问题、并发问题。
22. 阿⾥强制要求如果遇到需要表达是与否的概念时,必须使⽤ is_xxx 的⽅法命令,数据类型是 unsigned tinyint,1 表⽰是,0 表⽰否。
说明:任务字段如果为⾮负数,必须是 unsigned。
命名使⽤ is_xxx 第⼀个好处是⽐较清晰的,第⼆个好处是使⽤者根据命名就可以知道这个字段的取值范围,也⽅便做参数验证。类型使⽤unsigned 的好处是如果只存整数,
unsigned 类型有更⼤的取值范围,可以节约磁盘和内存使⽤。
23. 对于表的名字,MySQL 社区有⾃⼰推荐的命名规范:
1).表包含多个英⽂单词时,需要⽤下划线进⾏单词分割,这⼀点类似于 Java 类名的命名规范,例如 master_schedule、
security_user_permission;
2).由于 InnoDB 存储引擎本⾝是针对操作系统的可插拔设计的,所以原则上所有的表名组成全部由⼩写字母组成;
3).不允许出现空格,需要分割⼀律采⽤下划线;
4).名字不允许出现数字,仅包含英⽂字母;
5).名字需要总长度少于 64 个字符。
24. 数据类型精度考量:阿⾥强制要求存放⼩数时使⽤ decimal,禁⽌使⽤ float 和 double。
说明:float 和 double 在存储的时候,存在精度损失的问题,很可能在值的⽐较时,得到不正确的结果。如果存储的数据范围超过decimal 的范围,建议将数据拆成整数和⼩数分开存储。
实际上,所有涉及到数据存储的类型定义,都会涉及数据精度损失问题。Java 的数据类型也存在 float 和 double 精度损失情况,阿⾥没有指出这条规约,就全⽂来说,这是⼀个⽐较严重的规约缺失。
25. 采⽤ BigDecimal 有⼀个缺点,就是使⽤过程中没有原始数据这么⽅便,效率也不⾼。如果采⽤ int ⽅式,最好不要在有⼩数点的场景下使⽤,可以在 100、10 这样业务场景下选择使⽤。
26. 阿⾥强制要求如果存储的字符串长度⼏乎相等,使⽤ Char 定长字符串类型。
27. 服务间依赖关系:阿⾥推荐默认上层依赖于下层,箭头关系表⽰可直接依赖,如:开放接⼝层可以依赖于 Web 层,也可以直接依赖于Service 层。
28. 阿⾥推荐⾼并发服务器建议调⼩ TCP 协议的 time_wait 超时时间。
说明:操作系统默认 240 秒后才会关闭处于 time_wait 状态的连接,在⾼并发访问下,服务器端会因为处于 time_wait 的连接数太多,可能⽆法建⽴新的连接,所以需要在服务器上调⼩此等待值。
正例:在 Linux 服务器上通过变更/f ⽂件去修改该缺省值(秒):p_fin_timeout=30
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论