By Amap_tech team.
This article describes a set of coding rules relevant to Java functions and intends to give some coding advice to Java programmers, which will help them produce more elegant, higher quality, and more efficient code.
Refer to this link to view the first part of this article.
The following snippet shows the symptom description.
// 调用代码
double price = 5.1D;
int number = 9;
double total = calculate(price, number);
// 计算金额函数
private double calculate(Double price, Integer number) {
return price * number;
}
Refer to the following recommended solution.
// 调用代码
double price = 5.1D;
int number = 9;
double total = calculate(price, number);
// 计算金额函数
private double calculate(double price, int number) {
return price * number;
}
The following snippet shows the symptom description.
// 获取订单总额函数
public double getOrderAmount(List<Product> productList) {
double amount = 0.0D;
for (Product product : productList) {
if (Objects.isNull(product) || Objects.isNull(product.getPrice())
|| Objects.isNull(product.getNumber())) {
continue;
}
amount += calculate(product.getPrice(), product.getNumber());
}
return amount;
}
// 计算金额函数
private Double calculate(double price, double number) {
return price * number;
}
Refer to the following recommended solution.
// 获取订单总额函数
public double getOrderAmount(List<Product> productList) {
double amount = 0.0D;
for (Product product : productList) {
if (Objects.isNull(product) || Objects.isNull(product.getPrice())
|| Objects.isNull(product.getNumber())) {
continue;
}
amount += calculate(product.getPrice(), product.getNumber());
}
return amount;
}
// 计算金额函数
private double calculate(double price, double number) {
return price * number;
}
This example is for illustration purposes only. It would be better to use stream programming in this case.
The following snippet shows the symptom description.
// 调用代码
UserVO[] users = queryUser();
if (Objects.nonNull(users)) {
for (UserVO user : users) {
// 处理用户信息
}
}
// 查询用户函数
private UserVO[] queryUser() {
// 查询用户列表
List<UserDO> userList = userDAO.queryAll();
if (CollectionUtils.isEmpty(userList)) {
return null;
}
// 转化用户数组
UserVO[] users = new UserVO[userList.size()];
for (int i = 0; i < userList.size(); i++) {
UserDO user = userList.get(i);
users[i] = new UserVO();
users[i].setId(user.getId());
users[i].setName(user.getName());
}
// 返回用户数组
return users;
}
Refer to the following recommended solution.
// 调用代码
UserVO[] users = queryUser();
for (UserVO user : users) {
// 处理用户信息
}
// 查询用户函数
private UserVO[] queryUser() {
// 查询用户列表
List<UserDO> userList = userDAO.queryAll();
if (CollectionUtils.isEmpty(userList)) {
return new UserVO[0];
}
// 转化用户数组
UserVO[] users = new UserVO[userList.size()];
for (int i = 0; i < userList.size(); i++) {
UserDO user = userList.get(i);
users[i] = new UserVO();
users[i].setId(user.getId());
users[i].setName(user.getName());
}
// 返回用户数组
return users;
}
The following snippet shows the symptom description.
// 调用代码
List<UserVO> userList = queryUser();
if (Objects.nonNull(userList)) {
for (UserVO user : userList) {
// 处理用户信息
}
}
// 查询用户函数
private List<UserVO> queryUser(){
// 查询用户列表
List<UserDO> userList = userDAO.queryAll();
if(CollectionUtils.isEmpty(userList)) {
return null;
}
// 转化用户列表
List<UserVO> userVoList = new ArrayList<>(userList.size());
for(UserDO user : userList) {
UserVO userVo = new UserVO();
userVo.setId(user.getId());
userVo.setName(user.getName());
userVoList.add(userVo);
}
// 返回用户列表
return userVoList;
}
Refer to the following recommended solution.
// 调用代码
List<UserVO> userList = queryUser();
for (UserVO user : userList) {
// 处理用户信息
}
// 查询用户函数
private List<UserVO> queryUser(){
// 查询用户列表
List<UserDO> userList = userDAO.queryAll();
if(CollectionUtils.isEmpty(userList)) {
return Collections.emptyList();
}
// 转化用户列表
List<UserVO> userVoList = new ArrayList<>(userList.size());
for(UserDO user : userList) {
UserVO userVo = new UserVO();
userVo.setId(user.getId());
userVo.setName(user.getName());
userVoList.add(userVo);
}
// 返回用户列表
return userVoList;
}
Java specifications disallow too many function parameters, which makes it difficult to maintain and expand functions.
The following snippet shows the symptom description.
// 修改用户函数
public void modifyUser(Long id, String name, String phone, Integer age,
Integer sex, String address, String description) {
// 具体实现逻辑
}
Refer to the following recommended solution.
// 修改用户函数
public void modifyUser(User user) {
// 具体实现内容
}
// 用户类
@Getter
@Setter
@ToString
private class User{
private Long id;
private String name;
private String phone;
private Integer age;
private Integer sex;
private String address;
private String description;
}
Since parameters appear in groups, it is necessary to encapsulate a class to describe this situation.
The following snippet shows the symptom description.
// 获取距离函数
public double getDistance(double x1, double y1, double x2, double y2) {
// 具体实现逻辑
}
Refer to the following recommended solution.
// 获取距离函数
public double getDistance(Point point1, Point point2) {
// 具体实现逻辑
}
// 点类
@Getter
@Setter
@ToString
private class Point{
private double x;
private double y;
}
Advantages and disadvantages of anonymous internal classes in Java: In an anonymous internal class (including Lambda expressions), you may directly access the members of external classes, including the member variables of classes and the internal variables of functions. In this case, since you access external variables at will, the boundaries of the code are unclear.
We recommend using Lambda expressions to simplify anonymous internal classes and then employing functions to implement complex Lambda expressions.
The following snippet shows the symptom description.
// 发送结算数据
sendWorkerSettleData(WorkerPushDataType.CHECKER, () -> {
Date beginDate = DateUtils.addDays(currDate, -aheadDays);
Date endDate = DateUtils.addDays(currDate, 1);
return auditTaskDAO.statCheckerSettleData(beginDate, endDate);
});
Refer to the following recommended solution.
// 发送结算数据
sendWorkerSettleData(WorkerPushDataType.CHECKER, () -> statCheckerSettleData(currDate, aheadDays));
// 统计验收员结算数据函数
private List<WorkerSettleData> statCheckerSettleData(Date currDate, int aheadDays) {
Date beginDate = DateUtils.addDays(currDate, -aheadDays);
Date endDate = DateUtils.addDays(currDate, 1);
return auditTaskDAO.statCheckerSettleData(beginDate, endDate);
}
In fact, there is a simpler way. To calculate the start date and end date before calling the sendWorkerSettleData
function (to send data to the operator for settlement), use the function auditTaskDAO.statCheckerSettleData
(beginDate, endDate) instead of the anonymous internal class.
If the functions of the API implemented by an anonymous internal class are less relevant to each other, split the API into several functional APIs to facilitate the use of Lambda expressions.
The following snippet shows the symptom description.
// 清除过期数据
cleanExpiredData("用户日志表", new CleanExpiredDataOperator() {
@Override
public List<Date> queryExpiredDate(Integer remainDays) {
return userDAO.queryExpiredDate(remainDays);
}
@Override
public void cleanExpiredData(Date expiredDate) {
userDAO.cleanExpiredData(expiredDate);
}
});
// 清除过期数据函数
private void cleanExpiredData(String tableName, CleanExpiredDataOperator ,
cleanExpiredDataOperator) {
// 功能实现代码
}
// 清除过期操作接口
interface CleanExpiredDataOperator {
// 查询过期日期
public List<Date> queryExpiredDate(Integer remainDays);
// 清除过期数据
public void cleanExpiredData(Date expiredDate);
}
Refer to the following recommended solution.
// 清除过期数据
cleanExpiredData("用户日志表", userDAO::queryExpiredDate,userDAO::cleanExpiredData);
// 清除过期数据函数
private void cleanExpiredData(String tableName, QueryExpiredDateOperator queryExpiredDateOperator, CleanExpiredDataOperator cleanExpiredDataOperator) {
// 功能实现代码
}
// 查询过期日期接口
interface QueryExpiredDateOperator {
// 查询过期日期
public List<Date> queryExpiredDate(Integer remainDays);
}
// 清除过期操作接口
interface CleanExpiredDataOperator {
// 清除过期数据
public void cleanExpiredData(Date expiredDate);
}
The following snippet shows the symptom description.
// 是否通过函数
public boolean isPassed(Double passRate) {
if (Objects.nonNull(passRate) && passRate.compareTo(PASS_THRESHOLD) >= 0) {
return true;
}
return false;
}
Refer to the following recommended solution.
// 是否通过函数
public boolean isPassed(Double passRate) {
return Objects.nonNull(passRate) && passRate.compareTo(PASS_THRESHOLD) >= 0;
}
The following snippet shows the symptom description.
// 结算工资函数
public double settleSalary(Long workId, int workDays) {
// 根据是否合格处理
if (isQualified(workId)) {
return settleQualifiedSalary(workDays);
} else {
return settleUnqualifiedSalary(workDays);
}
}
Refer to the following recommended solution.
// 结算工资函数
public double settleSalary(Long workId, int workDays) {
// 根据是否合格处理
if (isQualified(workId)) {
return settleQualifiedSalary(workDays);
}
return settleUnqualifiedSalary(workDays);
}
The following snippet shows the symptom description.
// 查询用户函数
public List<UserDO> queryUser(Long id, String name) {
UserQuery userQuery = new UserQuery();
userQuery.setId(id);
userQuery.setName(name);
List<UserDO> userList = userDAO.query(userQuery);
return userList;
}
Refer to the following recommended solution.
// 查询用户函数
public List<UserDO> queryUser(Long id, String name) {
UserQuery userQuery = new UserQuery();
userQuery.setId(id);
userQuery.setName(name);
return userDAO.query(userQuery);
}
In some code segments, you often see the a.getB().getC()...getN()
syntax. This is referred to as a cascaded function call and results in poor code robustness and readability. We recommend that you should not perform cascaded function calls. Instead, use temporary variables to split the calls and perform null pointer checks on objects.
The following snippet shows the symptom description.
// 是否土豪用户函数
private boolean isRichUser(User user) {
return Objects.nonNull(user.getAccount())
&& Objects.nonNull(user.getAccount().getBalance())
&& user.getAccount().getBalance().compareTo(RICH_THRESHOLD) >= 0;
}
This is an easy method for simplified code control, but it results in poor readability.
Refer to the following recommended solution.
// 是否土豪用户函数
private boolean isRichUser(User user) {
// 获取用户账户
UserAccount account = user.getAccount();
if (Objects.isNull(account)) {
return false;
}
// 获取用户余额
Double balance = account.getBalance();
if (Objects.isNull(balance)) {
return false;
}
// 比较用户余额
return balance.compareTo(RICH_THRESHOLD) >= 0;
}
This solution increases code lines but clarifies the logic. When you find that it is difficult to balance simplicity and readability, we recommend weighing the readability more.
The following snippet shows the symptom description.
// 构建用户函数
public UserVO buildUser(UserDO user) {
UserVO vo = new UserVO();
vo.setId(user.getId());
vo.setName(user.getName());
if (Objects.nonNull(user.getAccount())) {
vo.setBalance(user.getAccount().getBalance());
vo.setDebt(user.getAccount().getDebt());
}
return vo;
}
The code is written this way to reduce temporary variables.
Refer to the following recommended solution.
// 构建用户函数
public UserVO buildUser1(UserDO user) {
UserVO vo = new UserVO();
vo.setId(user.getId());
vo.setName(user.getName());
UserAccount account = user.getAccount();
if (Objects.nonNull(account)) {
vo.setBalance(account.getBalance());
vo.setDebt(account.getDebt());
}
return vo;
}
In some code segments, you often see the a.getB().getC()...getN()
syntax. This is referred to as a cascaded function call and results in poor code robustness and readability. We recommend that you not perform cascaded function calls. Instead, use temporary variables to split the calls and perform null pointer checks on objects.
The following snippet shows the symptom description.
// 修改用户状态函数
private void modifyUserStatus(Long userId, Integer status, String unused) {
userCache.modifyStatus(userId, status);
userDAO.modifyStatus(userId, status);
}
其中,unused参数是无用参数。
建议方案:
// 修改用户状态函数
private void modifyUserStatus(Long userId, Integer status) {
userCache.modifyStatus(userId, status);
userDAO.modifyStatus(userId, status);
}
The following snippet shows the symptom description.
// 删除用户函数
private void deleteUser(User user) {
userCache.delete(user.getId());
userDAO.delete(user.getId());
}
Refer to the following recommended solution.
// 删除用户函数
private void deleteUser(Long userId) {
userCache.delete(userId);
userDAO.delete(userId);
}
When calling a function, there's no need to build a dedicated parameter object. When a function uses more than three attributes, you do not need to apply this rule.
Retain only the parameters required by the function to clarify the parameters that need to be assigned values during the call and avoid constructing useless parameters during the call.
If you have better suggestions or better code cases, we welcome your input. We hope that this article serves as a reference and contribute to the formation of a complete set of Java coding specifications.
Providing Education to Millions of Students while Schools Were Shut
2,606 posts | 737 followers
FollowAlibaba Clouder - April 29, 2020
Aliware - April 10, 2020
Aliware - November 4, 2019
Alibaba Cloud Community - February 14, 2022
Changyi - February 16, 2020
Alibaba Cloud Native - November 4, 2019
2,606 posts | 737 followers
FollowA cost-effective, efficient and easy-to-manage hybrid cloud storage solution.
Learn MoreAlibaba Cloud (in partnership with Whale Cloud) helps telcos build an all-in-one telecommunication and digital lifestyle platform based on DingTalk.
Learn MoreBuild superapps and corresponding ecosystems on a full-stack platform
Learn MoreProvides comprehensive quality assurance for the release of your apps.
Learn MoreMore Posts by Alibaba Clouder