alibaba开发手册

11.19

  1. 强制: 方法参数在定义和传入时,多个参数逗号后边必须加空格。

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

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

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

  5. 所有整型包装类对象之间值的比较,全部使用 equals 方法比较

  6. 浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用
    equals 来判断

  7. 数据库字段的 bigint 必须与类属性的 Long 类型相对应。

  8. 为了防止精度损失,禁止使用构造方法 BigDecimal(double)的方式把 double 值转
    化为 BigDecimal 对象

  9. 构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中。

  10. 循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。

  11. final 可以声明类、成员变量、方法、以及本地变量,下列情况使用 final 关键字:
    1) 不允许被继承的类,如:String 类。
    2) 不允许修改引用的域对象。
    3) 不允许被覆写的方法,如:POJO 类的 setter 方法。
    4) 不允许运行过程中重新赋值的局部变量。
    5) 避免上下文重复使用一个变量,使用 final 可以强制重新定义一个变量,方便更好地进行重构。

11.20

1.   使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一
   致、长度为 0 的空数组。
   反例:直接使用 toArray 无参方法存在问题,此方法返回值只能是 Object[]类,若强转其它类型数组将出
   现 ClassCastException 错误。  
2.   List<String> list = new ArrayList<>(2);
   list.add("guan");
   list.add("bao");
   String[] array = list.toArray(new String[0]);
   说明:使用 toArray 带参方法,数组空间大小的 length:
   1) 等于 0,动态创建与 size 相同的数组,性能最好。
   2) 大于 0 但小于 size,重新创建大小等于 size 的数组,增加 GC 负担。
   3) 等于 size,在高并发情况下,数组创建完成之后,size 正在变大的情况下,负面影响与上相同。
   4) 大于 size,空间浪费,且在 size 处插入 null 值,存在 NPE 隐患。  
3.   不要在 foreach 循环里进行元素的 remove/add 操作。 remove 元素请使用
   Iterator 方式,如果并发操作,需要对 Iterator 对象加锁。    正例:
   List<String> list = new ArrayList<>();
   list.add("1");
   list.add("2");
   Iterator<String> iterator = list.iterator();
   while (iterator.hasNext()) {
   String item = iterator.next();
   if (删除元素的条件) {
   Java 开发手册
   13/44
   iterator.remove();
   }
   }
   反例:
   for (String item : list) {
   if ("1".equals(item)) {
   list.remove(item);
   }
   }  
4. ArrayList 是 order/unsort;HashMap 是 unorder/unsort;TreeSet 是 order/sort。  
5.   【参考】 利用 Set 元素唯一的特性,可以快速对一个集合进行去重操作,避免使用 List 的
   contains 方法进行遍历、对比、 去重操作。  

11.21

​	并发处理

 1.   对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会
    造成死锁。  

 2.   并发修改同一记录时,避免更新丢失,需要加锁。 要么在应用层加锁,要么在缓存
    加锁,要么在数据库层使用乐观锁,使用 version 作为更新依据。
    说明:如果每次访问冲突概率小于 20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重试次数不得小于
    3 次  

    控制语句

    1.   在一个 switch 块内,每个 case 要么通过 continue/break/return 等来终止,要么
       注释说明程序将继续执行到哪一个 case 为止;在一个 switch 块内,都必须包含一个
       default 语句并且放在最后,即使它什么代码也没有。
       说明:注意 break 是退出 switch 语句块,而 return 是退出方法体  

    2.   在高并发场景中,避免使用” 等于” 判断作为中断或退出的条件。
       说明:如果并发控制没有处理好,容易产生等值判断被“击穿” 的情况,使用大于或小于的区间判断条件
       来代替。  

    3.   【推荐】 表达异常的分支时,少用 if-else 方式,这种方式可以改写成:
       if (condition) {
       ...
       return obj;
       }
       // 接着写 else 的业务逻辑代码  

    4. ```java
       package com.yamon.array;
       
       public class SwitchString {
           public static void main(String[] args) {
               method(null);
           }
           public static void method(String param) {
               switch (param) {
       // 肯定不是进入这里
                   case "sth":
                       System.out.println("it's sth");
                       break;
       // 也不是进入这里
                   case "null":
                       System.out.println("it's null");
                       break;
       // 也不是进入这里
                   default:
                       System.out.println("default");
               }
           }
       }
       ```

       ![image-20191121085237517](C:\Users\陈亚萌\AppData\Roaming\Typora\typora-user-images\image-20191121085237517.png)



5.   循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变
   量、获取数据库连接,进行不必要的 try-catch 操作(这个 try-catch 是否可以移至循环体
   外)  

11.22

1.   类、类属性、类方法的注释必须使用 Javadoc 规范,使用/**内容*/格式,不得使用
   // xxx 方式  
2.   所有的抽象方法(包括接口中的方法)必须要用 Javadoc 注释、除了返回值、参数、
   异常说明外,还必须指出该方法做什么事情,实现什么功能  
3.   代码修改的同时,注释也要进行相应的修改,尤其是参数、返回值、异常、核心逻
   辑等的修改。  
4.   错误,不能工作(FIXME):(标记人,标记时间,[预计处理时间])
   在注释中用 FIXME 标记某代码是错误的,而且不能工作,需要及时纠正的情况。  
5.   在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。  
6.   后台输送给页面的变量必须加$!{var}——中间的感叹号。 
7.   注意 Math.random() 这个方法返回是 double 类型,注意取值的范围 0≤x<1(能够
   取到零值,注意除零异常),如果想获取整数类型的随机数,不要将 x 放大 10 的若干倍然后
   取整,直接使用 Random 对象的 nextInt 或者 nextLong 方法。   
8.   获取当前毫秒数 System.currentTimeMillis(); 而不是 new Date().getTime();
   说明:如果想获取更加精确的纳秒级时间值,使用 System.nanoTime()的方式。在 JDK8 中,针对统计时
   间等场景,推荐使用 Instant 类。  
9.   日期格式化时,传入 pattern 中表示年份统一使用小写的 y。
   说明:日期格式化时,yyyy 表示当天所在的年,而大写的 YYYY 代表是 week in which year
   (JDK7 之后引入的概念),意思是当天所在的周属于的年份,一周从周日开始,周六结束,
   只要本周跨年,返回的 YYYY 就是下一年。另外需要注意:
   ⚫ 表示月份是大写的 M
   ⚫ 表示分钟则是小写的 m
   ⚫ 24 小时制的是大写的 H
   ⚫ 12 小时制的则是小写的 h
   正例:表示日期和时间的格式如下所示:
   new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
10.   任何数据结构的构造或初始化,都应指定大小,避免数据结构无限增长吃光内存。  
11.   **及时清理不再使用的代码段或配置信息。**
    说明:对于垃圾代码或过时配置,坚决清理干净,避免程序过度臃肿,代码冗余。
    正例:****对于暂时被注释掉,后续可能恢复使用的代码片断,在注释代码上方,统一规定使用三个斜杠(///)**
    来说明注释掉代码的理由。**  

二、异常日志

1.   捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,
   请将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理
   解的内容。  

2.   防止 NPE,是程序员的基本修养,注意 NPE 产生的场景:
   1) 返回类型为基本数据类型,return 包装数据类型的对象时,自动拆箱有可能产生 NPE。
   反例:public int f() { return Integer 对象}, 如果为 null,自动解箱抛 NPE。
   2) 数据库的查询结果可能为 null。
   3) 集合里的元素即使 isNotEmpty,取出的数据元素也可能为 null。
   4) 远程调用返回对象时,一律要求进行空指针判断,防止 NPE。
   5) 对于 Session 中获取的数据,建议进行 NPE 检查,避免空指针。
   6) 级联调用 obj.getA().getB().getC();一连串调用,易产生 NPE。
   正例:使用 JDK8 的 Optional 类来防止 NPE 问题。  

三、日志规约

   1.   应用中的扩展日志(如打点、临时监控、访问日志等)命名方式:
      appName_logType_logName.log。 logType:日志类型,如 stats/monitor/access 等;logName:日志
      描述。这种命名的好处:通过文件名就可知道日志文件属于什么应用,什么类型,什么目的,也有利于归
      类查找。  
   2.   避免重复打印日志,浪费磁盘空间,务必在 log4j.xml 中设置 additivity=false。  

四、单元测试

   1.   好的单元测试必须遵守 AIR 原则。
      说明:单元测试在线上运行时,感觉像空气(AIR)一样并不存在,但在测试质量的保障上,却是非常关
      键的。好的单元测试宏观上来说,具有自动化、独立性、可重复执行的特点。
      ⚫ A:Automatic(自动化)
      ⚫ I:Independent(独立性)
      ⚫ R:Repeatable(可重复)  

   2.   单元测试应该是全自动执行的,并且非交互式的。测试用例通常是被定期执行的,
      执行过程必须完全自动化才有意义。输出结果需要人工检查的测试不是一个好的单元测试。
      单元测试中不准使用 System.out 来进行人肉验证,必须使用 assert 来验证。  

11.25

1. 用户请求传入的任何参数必须做有效性验证。
	说明:忽略参数校验可能导致:
	⚫ page size 过大导致内存溢出
	⚫ 恶意 order by 导致数据库慢查询
	⚫ 任意重定向
	⚫ SQL 注入
	⚫ 反序列化注入
	⚫ 正则输入源串拒绝服务 ReDoS
	说明:Java 代码用正则来验证客户端的输入,有些正则写法验证普通用户输入没有问题,但是如果攻
	击人员使用的是特殊构造的字符串来验证,有可能导致死循环的结果。
2. 发贴、评论、发送即时消息等用户生成内容的场景必须实现防刷、文	本内容违禁词过滤等风控策略。

数据库安全

1.  表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类	型是 unsigned
	tinyint(1 表示是,0 表示否)
2. 表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。
3. 表名不使用复数名词。
4. 小数类型为 decimal,禁止使用 float 和 double
5. varchar 是可变长字符串,不预先分配存储空间,长度不要超过 	5000,如果存储长度大于此值,定义字段类型为 text,独立
	出来一张表,用主键来对应,避免影响其它字段索引效率
6. 表必备三字段:id, create_time, update_time
7. 表的命名最好是遵循“业务名称_表的作用” 。

11.27

工程结构

应用分层

  1. 定义 GAV 遵从以下规则:
  2. 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:详细规定参考下方
  4. 禁止在子项目的 pom 依赖中出现相同的 GroupId,相同的 ArtifactId,但是不同的
    Version。
 posted on 2019-11-27 15:08  ben跑的换行符  阅读(384)  评论(0编辑  收藏  举报