**阿里Java开发手册重点总结**
- 【强制】POJO 类中的任何布尔类型的变量,都不要加 is 前缀,否则部分框架解析会引起序列
化错误。
需要在xml里的设置从 is_xxx 到 xxx 的映射关系。
-
【强制】不允许任何魔法值(即未经预先定义的常量)直接出现在代码中。
-
【强制】单行字符数限制不超过 120 个,超出需要换行,换行时遵循如下原则:
1) 第二行相对第一行缩进 4 个空格,从第三行开始,不再继续缩进,参考示例。
2) 运算符与下文一起换行。
3) 方法调用的点符号与下文一起换行。
4) 方法调用中的多个参数需要换行时,在逗号后进行。
5) 在括号前不要换行
-
【强制】Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。
-
【强制】所有整型包装类对象之间值的比较,全部使用 equals 方法比较
说明:对于 Integer var = ? 在-128 至 127 之间的赋值,
Integer 对象是在 IntegerCache.cache 产生,
会复用已有对象,这个区间内的 Integer 值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。
6. 【强制】定义数据对象 DO 类时,属性类型要与数据库字段类型相匹配。
正例:数据库字段的 bigint 必须与类属性的 Long 类型相对应
7. 【强制】禁止在 POJO 类中,同时存在对应属性 xxx 的 isXxx()和 getXxx()方法。
说明:框架在调用属性 xxx 的提取方法时,并不能确定哪个方法一定是被优先调用到,神坑之一
8.【强制】获取当前毫秒数:System.currentTimeMillis(); 而不是 new Date().getTime()。说
明:如果想获取更加精确的纳秒级时间值,使用 System.nanoTime 的方式。在 JDK8 中,针对统计时间等
场景,推荐使用 Instant 类。
9.【强制】关于 hashCode 和 equals 的处理,遵循如下规则:
1) 只要重写 equals,就必须重写 hashCode。
2) 因为 Set 存储的是不重复的对象,依据 hashCode 和 equals 进行判断,所以 Set 存储的对象必须重写
这两个方法。
3) 如果自定义对象作为 Map 的键,那么必须覆写hashCode 和 equals。
说明:String 因为重写了 hashCode 和 equals 方法,所以我们可以愉快地使用 String 对象作为 key 来使
用。
10.【强制】在使用 java.util.stream.Collectors 类的 toMap()方法转为 Map 集合时,一定要使
用含有参数类型为 BinaryOperator,参数名为 mergeFunction 的方法,否则当出现相同 key
值时会抛出 IllegalStateException 异常。
说明:参数 mergeFunction 的作用是当出现 key 重复时,自定义对 value 的处理策略。
正例:
List<Pair<String, Double>> pairArrayList = new ArrayList<>(3);
pairArrayList.add(new Pair<>("version", 6.19));
pairArrayList.add(new Pair<>("version", 10.24));
pairArrayList.add(new Pair<>("version", 13.14));
Map<String, Double> map = pairArrayList.stream().collect(
// 生 成 的 map 集 合 中 只 有 一 个 键 值 对 :
{version=13.14}
Collectors.toMap(Pair::getKey, Pair::getValue, (v1, v2) -> v2));
11.【强制】在使用 java.util.stream.Collectors 类的 toMap()方法转为 Map 集合时,一定要注
意当 value 为 null 时会抛 NPE 异常。说明:在 java.util.HashMap 的 merge 方法里会进行如下的判断: if (value == null || remappingFunction == null) throw
12.【强制】使用 Map 的方法 keySet()/values()/entrySet()返回集合对象时,不可以对其进行添
加元素操作,否则会抛出 UnsupportedOperationException 异常。
13. 【强制】Collections 类返回的对象,如:emptyList()/singletonList()等都是 immutable list,
不可对其进行添加或者删除元素的操作。
反例:如果查询无结果,返回 Collections.emptyList()空集合对象,调用方一旦进行了添加元素的操作,就
会触发 UnsupportedOperationException 异常。
14.【强制】在使用 Collection 接口任何实现类的 addAll()方法时,都要对输入的集合参数进行
NPE 判断。
说明:在 ArrayList#addAll 方法的第一行代码即 Object[] a = c.toArray(); 其中 c 为输入集合参数,如果
为 null,则直接抛出异常。
项目规范 总结****
1.判断不为空
1)TbChanceTypeConfig typeConfig = CheckReferenceUtils.checkNotNull(chanceTypeConfigDao.selectByPrimaryKey(dto.getId()), ResultEnum.CHANCE_NOT_EXIST);
2) if (!CollectionUtils.isEmpty(list)) {
}
3) if (StringUtils.isEmpty(marketBusinessTrackingDto.getReason())) {
throw new BizException(ResultEnum.MARKET_BUSINESS_REASON_ERROR);
}
2.Map的使用
1)避免循环中进行数据库操作,尽量在循环外获取数据,组装map,循环内取用
2)Map注意重复键的情况
3)key需要多个属性值组装时尽量使用“-”隔开
3.Xml里尽量不使用连接查询
4.若以list作为方法的返回值 尽量使用定义好的vo 更加清晰 可读性强
反:List<HashMap<String, Object>> 正:List
5.导入组件上下文中进行全量数据的整合,用字段当作key 在业务校验时和peocess中获取上下文对象并获取对应map,map尽量只存所需字段 然后进行取值或判断 异常处理时将某行或某字段抛出异常
-
自定义异常拼接 ResultEnum中使用%s进行占位 QIFU_REPETITIVE_DATA("855", "%s(%s)信息已经由%s在%s提交,请知晓")
-
跨服务之间的 文件直接用MultipartFile file文件接收前端参数 被调用服务方需要 加入注解 @PostMapping(value = "/importCompany", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
-
数据库中新创建的表在上线之前,ddl要删掉主键自动生成起始值
9.自定义异常抛Biz异常,精确描述,方便问题寻找throw new BizException(ResultEnum.CHANCE_NOT_EXIST) ;
10.通过缓存访问次数、缓存一致性等多方面考虑类上有没有必要加缓存再考虑方法上是否需要加缓存 缓存注解@Cacheable 添加缓存 @CacheEvict清理redis缓存
12.更新数据时必须先将数据查出赋值后再执行更新操作
13.EnumUtils.getByCodeOrThrow(OrgEnum.class, dto.getOrgCode()).getIsAnalysisOrg()){}
OrgEnum需要实现BaseEnum重写getCode方法
14.BigDecimal
1)BigDecimal.ZERO BigDecimal.ONE BigDecimal.TEN 如需其他数值需提前定义 切忌魔法值
2)去除尾随零方法stripTrailingZeros
3)防止导出文件中的数字过大变为科学计数法 可以采用注解@ContentStyle(dataFormat = 2)
4)除法必先判断除数是否为零
15.lisPage流程 先count(dto)为0(Constants.COUNT_VALUE_ZERO)则返回空Page对象不为空再进行listPage方法
16.入库时能放入List进行批量添加或者更新的话 应该优先考虑
17.数据库
1)除id外必备三字段
2)建命中率高的索引,能建唯一索引必须建唯一索引,唯一索引需要尽早建 避免添加脏数据
3)有一定关联的表 相同含义的字段名称保持一致
18.开发过程中及时format、清理无用代码、阿里规范扫描
19.单元测试代码要与生产代码分离,并且保持相同的代码质量与格式。使用断言的方式验证,对一些远程调用或不影响测试的方法等进行mock。
20.文件
文件先上传,上传后会返回文件id,添加操作时前端传入文件id,先进行业务数据入库,入库后业务数据中拿主键id,再与文件id进行绑定