The above background

This article summarizes a set of coding rules related to Java functions, aiming to give the majority of Java programmers some coding suggestions, help you write more elegant, higher quality, more efficient code.

Use basic types for internal function arguments whenever possible

Example 1: Use basic types for internal function arguments

Symptom Description:

// Double price = 5.1d; int number = 9; double total = calculate(price, number); Private double calculate(double price, Integer number) {return price * number;
}
Copy the code

Recommended scheme:

// Double price = 5.1d; int number = 9; double total = calculate(price, number); Private double calculate(double price, int number) {return price * number;
}
Copy the code

Case 2: Use the base type as much as possible for the internal function return value

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());
    }
    returnamount; } private Double calculate(Double price, Double number) {return price * number;
}
Copy the code

Recommended scheme:

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());
    }
    returnamount; } private double calculate(double price, double number) {return price * number;
}
Copy the code

To illustrate this phenomenon, a better approach is to use Stream programming.

The main benefits

  • Internal functions use basic types as much as possible, avoiding implicit packaging and unpacking of encapsulated types.
  • Internal function parameters use basic types, using syntax to avoid the internal function parameter null pointer judgment;
  • The return value of the internal function uses the underlying type, which syntactically avoids null pointer judgment of the return value of the calling function.

Try to avoid returning null arrays and lists

Case 1: Try to avoid returning array null, causing unnecessary null pointer judgment

Symptom Description:

UserVO[] users = queryUser();if (Objects.nonNull(users)) {
    for(UserVO user: users) {// Handle user information}} // Query user function private UserVO[]queryUserList<UserDO> userList = userdao.queryAll ();if (CollectionUtils.isEmpty(userList)) {
        returnnull; 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 an array of usersreturn users;
}
Copy the code

Recommended scheme:

UserVO[] users = queryUser();for(UserVO user: users) {// Handle user information} // Query user function private UserVO[]queryUserList<UserDO> userList = userdao.queryAll ();if (CollectionUtils.isEmpty(userList)) {
        returnnew 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 an array of usersreturn users;
}
Copy the code

Case 2: Try not to return the list as null, causing unnecessary null pointer judgment

Symptom Description:

List<UserVO> userList = queryUser();if (Objects.nonNull(userList)) {
    for(UserVO user: userList) {private List<UserVO> private List<UserVO>queryUserList<UserDO> userList = userdao.queryAll ();if(CollectionUtils.isEmpty(userList)) {
        returnnull; 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 to the user listreturn userVoList;
}
Copy the code

Recommended scheme:

List<UserVO> userList = queryUser();for(UserVO user: userList) {private List<UserVO>queryUserList<UserDO> userList = userdao.queryAll ();if(CollectionUtils.isEmpty(userList)) {
        returnCollections.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 to the user listreturn userVoList;
}
Copy the code

The main benefits

  • Ensure that the returned array and list are not null to avoid calling the null pointer to the function.

Encapsulate the function passing in parameters

Case 1: When too many parameters are passed in, encapsulate them as parameter classes

The Java specification does not allow functions to take too many arguments, making them difficult to maintain or extend.

Symptom Description:

Public void modifyUser(Long ID, String name, String phone, Integer age, Integer sex, String address, String description) {// Implement logic}Copy the code

Recommended scheme:

Public void modifyUser(User User) {// Implementation content} // User class @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; }Copy the code

When a group parameter is passed, it should be encapsulated as a parameter class

Now that arguments are grouped, you need to encapsulate a class to describe this phenomenon.

Symptom Description:

Public double getDistance(double x1, double y1, double x2, double y2) {Copy the code

Recommended scheme:

Public double getDistance(Point point1, Point point2) {getter@setter@toString private class Point{private double x; private double y; }Copy the code

The main benefits

  • Encapsulate too many function parameters as classes, making the function easier to expand and maintain;
  • Encapsulate group function parameters as classes to make business concepts clearer and clearer.

Replace anonymous inner class implementations with functions whenever possible

Advantages and disadvantages of Java anonymous inner classes: In anonymous inner classes (including Lambda expressions), you can directly access the members of the outer class, including the member variables of the class and the internal variables of the function. Because external variables can be accessed at will, code boundaries are not clear.

Lambda expressions are recommended first to simplify anonymous inner classes, and functions to replace complex implementations of Lambda expressions are recommended second.

Case 1: Try to replace implementations of anonymous inner classes (including Lambda expressions) with functions

Symptom Description:

/ / send the settlement data sendWorkerSettleData (WorkerPushDataType. The CHECKER, () - > {Date beginDate = DateUtils. AddDays (currDate, -aheadDays); Date endDate = DateUtils.addDays(currDate, 1);return auditTaskDAO.statCheckerSettleData(beginDate, endDate);
});
Copy the code

Recommended scheme:

/ / send the settlement data sendWorkerSettleData (WorkerPushDataType. The 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);
}
Copy the code

Well, there’s an easier way. Calculate the start and end dates before calling sendWorkerSettleData. Can use it directly function auditTaskDAO. StatCheckerSettleData (beginDate, endDate) instead of an anonymous inner class implements.

Case 2: Split complex anonymous inner class implementation interfaces into multiple functional class interfaces

If an anonymous inner class implements an interface whose functions are not closely related, you can split the interface into several functional interfaces for the convenience of Lambda expressions.

Symptom Description:

// cleanExpiredData("User Log table", new CleanExpiredDataOperator() {
    @Override
    public List<Date> queryExpiredDate(Integer remainDays) {
        returnuserDAO.queryExpiredDate(remainDays); } @Override public void cleanExpiredData(Date expiredDate) { userDAO.cleanExpiredData(expiredDate); }}); Private void cleanExpiredData(String tableName, CleanExpiredDataOperator, Interface cleanExpiredDataOperator {// Query expiration Date public List<Date> queryExpiredDate(Integer remainDays); Public void cleanExpiredData(Date expiredDate); }Copy the code

Recommended scheme:

// cleanExpiredData("User Log table", userDAO::queryExpiredDate,userDAO::cleanExpiredData); / / remove obsolete data function private void cleanExpiredData (String tableName, QueryExpiredDateOperator QueryExpiredDateOperator, CleanExpiredDataOperator CleanExpiredDataOperator) {interface QueryExpiredDateOperator {// Public List<Date> queryExpiredDate(Integer remainDays); } interface CleanExpiredDataOperator {public void cleanExpiredData(Date expiredDate); }Copy the code

The main benefits

  • The code boundary of anonymous inner class is specified by defining functions and specifying parameters.
  • Use Lambda expressions to simplify anonymous inner class implementations, making the code more concise.

Use returns to streamline unnecessary code

Case 1: Delete unnecessary if

Symptom Description:

Public Boolean isPassed(Double passRate) {public Boolean isPassed(Double passRate) {if (Objects.nonNull(passRate) && passRate.compareTo(PASS_THRESHOLD) >= 0) {
        return true;
    }
    return false;
}
Copy the code

Recommended scheme:

Public Boolean isPassed(Double passRate) {public Boolean isPassed(Double passRate) {return Objects.nonNull(passRate) && passRate.compareTo(PASS_THRESHOLD) >= 0;
}
Copy the code

Case 2: Delete unnecessary else

Symptom Description:

Public double settleSalary(Long workId, int workDays) {public double settleSalary(Long workId, int workDays)if (isQualified(workId)) {
        return settleQualifiedSalary(workDays);
    } else {
        returnsettleUnqualifiedSalary(workDays); }}Copy the code

Recommended scheme:

Public double settleSalary(Long workId, int workDays) {public double settleSalary(Long workId, int workDays)if (isQualified(workId)) {
        return settleQualifiedSalary(workDays);
    }
    return settleUnqualifiedSalary(workDays);
}
Copy the code

Case 3: Delete unnecessary variables

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;
}
Copy the code

Recommended scheme:

Public List<UserDO> queryUser(Long ID, String name) {UserQuery UserQuery = new UserQuery(); userQuery.setId(id); userQuery.setName(name);return userDAO.query(userQuery);
}
Copy the code

The main benefits

  • Simplify unnecessary code to make it look cleaner

Optimize your code with temporary variables

In some code, it is common to see a.geb ().getc ()… The way getN() is written, let’s call it “cascading calls to functions,” is not robust and readable. Suggestion: eliminate cascading function calls, use temporary variables to split, and do a good job of object null pointer check.

Case 1: Use temporary variables to clarify logic

Symptom Description:

Private Boolean isRichUser(User User) {private Boolean isRichUser(User User) {return Objects.nonNull(user.getAccount())
        && Objects.nonNull(user.getAccount().getBalance())
        && user.getAccount().getBalance().compareTo(RICH_THRESHOLD) >= 0;
}
Copy the code

This is a favorite of code lite geeks, but very unreadable.

Recommended scheme:

Private Boolean isRichUser(User User) {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; } // Compare user balancesreturn balance.compareTo(RICH_THRESHOLD) >= 0;
}
Copy the code

This solution increases the number of lines of code, but the logic is clearer. Sometimes, individuals prefer to preserve the readability of code when the simplicity and readability of code conflict.

Case 2: Simplify code with temporary variables

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;
}
Copy the code

I’m writing it this way to save a temporary variable.

Recommended scheme:

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;
}
Copy the code

The main benefits

  • Using temporary variables to clarify logic, business logic is more clear;
  • Using temporary variables to simplify the code, see the name of the variable to know its meaning, reduce a lot of useless code;
  • If the acquisition function is complicated and time-consuming, using temporary variables can improve the operation efficiency;
  • Using temporary variables to avoid cascading function calls can effectively prevent null pointer anomalies.

Keep only the parameters needed by the function

In some code, it is common to see a.geb ().getc ()… The way getN() is written, let’s call it “cascading calls to functions,” is not robust and readable. Suggestion: eliminate cascading function calls, use temporary variables to split, and do a good job of object null pointer check.

Case 1: Delete unnecessary parameters

Symptom Description:

Private void modifyUserStatus(Long userId, Integer status, String unused) {userCache.modifyStatus(userId, String unused) status); userDAO.modifyStatus(userId, status); }Copy the code

Unused parameter indicates an unused parameter.

Recommended scheme:

Private void modifyUserStatus(Long userId, Integer status) {userCache.modifyStatus(userId, status); private void modifyUserStatus(Long userId, Integer status) {userCache. userDAO.modifyStatus(userId, status); }Copy the code

Case 2: Replace objects with properties

Symptom Description:

Private void deleteUser(User User) {usercache.delete (user.getid ()); private void deleteUser(User User) {usercache.delete (user.getid ()); userDAO.delete(user.getId()); }Copy the code

Recommended scheme:

Private void deleteUser(Long userId) {usercache.delete (userId); private void deleteUser(Long userId) {usercache.delete (userId); userDAO.delete(userId); }Copy the code

Recommended scheme:

When a function is called, the parameter object does not need to be specially constructed, and the function uses more than three of its attributes, so you do not need to use this rule.

The main benefits

  • Only the parameters needed by the function are reserved, which makes it clear which parameters need to be assigned during the call, avoiding the need to construct some useless parameters during the call.

Afterword.

“Many hands make light work.” If you have a better point of view, or a better code example, I welcome you to add. I hope this article will lead to a complete set of Java coding specifications.