(一)让一个java程序员流泪,这样做就对了
说明
最近接手了一个同事写的代码,让我深深的怀疑人生,摘录几条,仅供娱乐,如有吐槽错误之处,大家手下留情。
部分代码做了过滤处理,尽可能的表达作者的原意,后续可能持续补充。
对象赋值
Dto 的 String 属性值默认是 null,直接 set 就行了,这个if加个就很有灵性。
if (aDto.getAValue() != null) {
bDto.setBValue(aDto.getAValue());
}
对象赋值
非要写的话不需要中间变量也是可以的,不过在设计的时候怎么没统一类型呢?
boolean show = false;
if (contOutDto.getHide() == 0) {
show = true;
}
infoDto.setShow(show);
列表的赋值与取值
可能这样更加热乎吧
List<CustomerDto> dataList=manageMapper.viewCustomers(code);
PageInfo<CustomerDto> dataListPage = new PageInfo<>(dataList);
List<CustomerDto> list = dataListPage.getList();
列表赋值
修改列表属性,非要返回也不会有什么问题,严重的是,有可能在别的代码里无意地更改数据。
List<ContDto> queryContInformation(List<ContDto> contList) {
//修改列表属性
return contList;
}
作为入参基本类型和引用类型效果是不同的
基本类型:值存放在局部变量表中,无论如何修改只会修改当前栈帧的值,方法执行结束对方法外不会做任何改变;此时需要改变外层的变量,必须返回主动赋值。
引用数据类型:指针存放在局部变量表中,调用方法的时候,副本引用压栈,意味着如果将引用重新赋值,不会修改原有的引用指向,但是如果修改了引用地址的对象属性,此时方法以外的引用此地址对象当然被修改。
//修改列表引用指向,不会影响外部 contList
void queryContInformation(List<ContDto> contList) {
contList = new ArrayList<>();
}
//修改列表属性会影响contList
void queryContInformation(List<ContDto> contList) {
//修改ContDto 的属性
}
if else 之外的条件
不到10 行的代码,逐个分析一下
- connectionEntity.getPersonFlag() 频繁使用,每次都 get,却不提取一个变量出来;
- 枚举类 ManageEnum 的属性 “ONE_STR”,命名很随意的样子;
- setPersonFlag 从代码结果来看,不是 0 就是 1,中间的 else if 就显得很多余了;
- 从整体编码来看,设计两个属性更加友好。
if (StringUtils.isNotEmpty(connectionEntity.getPersonFlag())
&& StringUtils.equals(userCode, connectionEntity.getPersonFlag())) {
dataDto.setPersonFlag(ManageEnum.ZERO_STR.getMsg());
} else if (StringUtils.isNotEmpty(connectionEntity.getPersonFlag())
&& !StringUtils.equals(userCode, connectionEntity.getPersonFlag())) {
dataDto.setPersonFlag(ManageEnum.ONE_STR.getMsg());
} else {
dataDto.setPersonFlag(ManageEnum.ONE_STR.getMsg());
}
HashMap 的初始化
HashMap 在初始化完成,添加第一个元素的时候,底层存储数据的数组 table 的属性为null,调用 resize 方法扩容至 16,因此初始值 2 是没有用的。好奇搜了一下,发现初始值是 2,3,4,5 的有很多,可怕的是,有一行还是本人写的,吓得我赶紧关闭了显示器。
Map<String, Object> paraMap = new HashMap<>(2);
另外
列表修改属性
- 如果列表再业务中不涉及到下标的操作,直接用增强for就行了,不用修改完了再用 setX() 方法;
- 在业务开发中,删除一般是做的逻辑删除,在查询的时候 del_status 直接写在查询 sql 就行了,没必要提出来,并且,这个枚举值怎么这么熟悉,哦,原来是在另外一个地方表示了其它业务含义,真的是最大化的利用了这个枚举常量值!此时我不觉地留下了没有技术的泪水。
- try{}catch{} 一般写在 for 循环的外边。
for (int i = 0; i < contList.size(); i++) {
ContDto contDto = contList.get(i);
List<ContAtrDto> contAtrDtos;
try {
//ZERO_STR 刪除状态标识
contAtrDtos = mangerMapper.queryContProperties(contDto.getContCode(), ManageEnum.ZERO_STR.getMsg());
} catch (Exception e) {
//other
}
if (CollectionUtils.isNotEmpty(contAtrDtos)) {
contDto.setcontAtrDtos(contAtrDtos);
contList.set(i, contDto);
}
}
经过修改
try {
for (ContDto contDto : contList) {
List<ContAtrDto> contAtrDtos = manageMapper.queryContProperties(contDto.getContCode());
if (CollectionUtils.isNotEmpty(contAtrDtos)) {
contDto.setcontAtrDtos(contAtrDtos);
}
}
} catch (Exception e) {
//other
}
如果条件允许,contDto.setcontAtrDtos(contAtrDtos); 也可不用加校验,在取值的时候再次校验
列表移除元素
for 循环移除元素,风险极大,遇到相同元素在一起的,存在漏删的情况。
编码不慎,会导致下标越界。
可以选择逆序删除的方法,或者使用 java8 的 stream 流的形式用新列表接收。
for (int i = 0; i < dictSubByCode.size(); i++) {
if ("1".equals(dictSubByCode.get(i).getDictCode())) {
dictSubByCode.remove(i);
}
}
//stream 优化
List<DictDto> collect = dictSubByCode.stream().filter(v -> !"1".equals(v.getDictCode())).collect(Collectors.toList());
// 更简单的方式
List<User> list = new ArrayList<>();
User user = new User();
user.setName("xm");
list.add(user);
list.removeIf(v->"".equals(v.getName()));
批量更新数据库数据
批量更新数据库数据,mybatis 有一个foreach 的动态标签。
for (BusinessEntity businessEntity : contData) {
boolean flag = businessDataMapper.updateContDate(businessEntity);
}
问题找的差不多了,这些都是一些基础的东西,稍微学习下也就不会犯这种错了,要改的话也能改改。
代码里还有两个方法复杂度超过了100,这两个方法里充斥着大量的 if else 还有for 循环的嵌套,业务也极度复杂,已经完全的超出了本人的认知。。。
写到这里,本人的眼泪也流干了。