(一)让一个java程序员流泪,这样做就对了

本文通过实例分析了一位Java程序员在处理对象赋值、列表操作、条件判断、HashMap初始化及数据库批量更新等场景时遇到的问题,揭示了一些常见的编程误区和不规范做法,包括不必要的if-else、列表元素修改、HashMap初始化错误等,并提出了改进方案,旨在提高代码质量和可维护性。
摘要由CSDN通过智能技术生成

说明

最近接手了一个同事写的代码,让我深深的怀疑人生,摘录几条,仅供娱乐,如有吐槽错误之处,大家手下留情。
部分代码做了过滤处理,尽可能的表达作者的原意,后续可能持续补充。

对象赋值

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 行的代码,逐个分析一下

  1. connectionEntity.getPersonFlag() 频繁使用,每次都 get,却不提取一个变量出来;
  2. 枚举类 ManageEnum 的属性 “ONE_STR”,命名很随意的样子;
  3. setPersonFlag 从代码结果来看,不是 0 就是 1,中间的 else if 就显得很多余了;
  4. 从整体编码来看,设计两个属性更加友好。

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);

另外

列表修改属性

  1. 如果列表再业务中不涉及到下标的操作,直接用增强for就行了,不用修改完了再用 setX() 方法;
  2. 在业务开发中,删除一般是做的逻辑删除,在查询的时候 del_status 直接写在查询 sql 就行了,没必要提出来,并且,这个枚举值怎么这么熟悉,哦,原来是在另外一个地方表示了其它业务含义,真的是最大化的利用了这个枚举常量值!此时我不觉地留下了没有技术的泪水。
  3. 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 循环的嵌套,业务也极度复杂,已经完全的超出了本人的认知。。。

写到这里,本人的眼泪也流干了。

(二)让一个java程序员流泪,这样做就对了.

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值