总结了大量的 Java 代码精简之道,非常棒!

反射机制数据库万能查询代码简化 代码有些地还有待完善。如有问题请大家反馈,谢谢! 立即下载

前言


 

古语有云:

道为术之灵,术为道之体;以道统术,以术得道。

其中:“道”指“规律、道理、理论”,“术”指“方法、技巧、技术”。意思是:“道”是“术”的灵魂,“术”是“道”的肉体;可以用“道”来统管“术”,也可以从“术”中获得“道”。

 

在拜读大佬“孤尽”的文章《Code Review是苦涩但有意思的修行》时,感受最深的一句话就是:“优质的代码一定是少即是多的精兵原则”,这就是大佬的代码精简之“道”。

 

工匠追求“术”到极致,其实就是在寻“道”,且离悟“道”也就不远了,亦或是已经得道,这就是“工匠精神”——一种追求“以术得道”的精神。如果一个工匠只满足于“术”,不能追求“术”到极致去悟“道”,那只是一个靠“术”养家糊口的工匠而已。作者根据多年来的实践探索,总结了大量的 Java 代码精简之“术”,试图阐述出心中的 Java 代码精简之“道”。

 

 

1.利用语法


 

1.1.利用三元表达式

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
String title;if (isMember(phone)) {    title = "会员";} else {    title = "游客";}

 

精简:


 
  •  
String title = isMember(phone) ? "会员" : "游客";

 

注意:对于包装类型的算术计算,需要注意避免拆包时的空指针问题。

 

1.2.利用 for-each 语句

 

从 Java 5 起,提供了 for-each 循环,简化了数组和集合的循环遍历。 for-each  循环允许你无需保持传统 for 循环中的索引就可以遍历数组,或在使用迭代器时无需在 while 循环中调用 hasNext 方法和 next 方法就可以遍历集合。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
double[] values = ...;for(int i = 0; i < values.length; i++) {    double value = values[i];    // TODO: 处理value}
List<Double> valueList = ...;Iterator<Double> iterator = valueList.iterator();while (iterator.hasNext()) {    Double value = iterator.next();    // TODO: 处理value}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
double[] values = ...;for(double value : values) {    // TODO: 处理value}
List<Double> valueList = ...;for(Double value : valueList) {    // TODO: 处理value}

 

1.3.利用 try-with-resource 语句

 

所有实现 Closeable 接口的“资源”,均可采用 try-with-resource 进行简化。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
BufferedReader reader = null;try {    reader = new BufferedReader(new FileReader("cities.csv"));    String line;    while ((line = reader.readLine()) != null) {        // TODO: 处理line    }} catch (IOException e) {    log.error("读取文件异常", e);} finally {    if (reader != null) {        try {            reader.close();        } catch (IOException e) {            log.error("关闭文件异常", e);        }    }}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {    String line;    while ((line = reader.readLine()) != null) {        // TODO: 处理line    }} catch (IOException e) {    log.error("读取文件异常", e);}

 

1.4.利用 return 关键字

 

利用 return 关键字,可以提前函数返回,避免定义中间变量。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public static boolean hasSuper(@NonNull List<UserDO> userList) {    boolean hasSuper = false;    for (UserDO user : userList) {        if (Boolean.TRUE.equals(user.getIsSuper())) {            hasSuper = true;            break;        }    }    return hasSuper;}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public static boolean hasSuper(@NonNull List<UserDO> userList) {    for (UserDO user : userList) {        if (Boolean.TRUE.equals(user.getIsSuper())) {            return true;        }    }    return false;}

 

1.5.利用 static 关键字

 

利用 static 关键字,可以把字段变成静态字段,也可以把函数变为静态函数,调用时就无需初始化类对象。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public final class GisHelper {    public double distance(double lng1, double lat1, double lng2, double lat2) {        // 方法实现代码    }}

GisHelper gisHelper = new GisHelper();double distance = gisHelper.distance(116.178692D, 39.967115D, 116.410778D, 39.899721D);

 

精简:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
public final class GisHelper {    public static double distance(double lng1, double lat1, double lng2, double lat2) {        // 方法实现代码    }}
double distance = GisHelper.distance(116.178692D, 39.967115D, 116.410778D, 39.899721D);

 

1.6.利用 lambda 表达式

 

Java 8 发布以后,lambda 表达式大量替代匿名内部类的使用,在简化了代码的同时,更突出了原有匿名内部类中真正有用的那部分代码。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
new Thread(new Runnable() {    public void run() {        // 线程处理代码    }}).start();

 

精简:


 
  •  
  •  
  •  
new Thread(() -> {    // 线程处理代码}).start();

 

1.7.利用方法引用

 

方法引用(::),可以简化 lambda 表达式,省略变量声明和函数调用。

 

普通:


 
  •  
  •  
  •  
  •  
Arrays.sort(nameArray, (a, b) -> a.compareToIgnoreCase(b));List<Long> userIdList = userList.stream()    .map(user -> user.getId())    .collect(Collectors.toList());

 

精简:

  •  
  •  
  •  
  •  
Arrays.sort(nameArray, String::compareToIgnoreCase);List<Long> userIdList = userList.stream()    .map(UserDO::getId)    .collect(Collectors.toList());

 

1.8.利用静态导入

 

静态导入(import static),当程序中大量使用同一静态常量和函数时,可以简化静态常量和函数的引用。

 

普通:


 
  •  
  •  
List<Double> areaList = radiusList.stream().map(r -> Math.PI * Math.pow(r, 2)).collect(Collectors.toList());...

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
import static java.lang.Math.PI;import static java.lang.Math.pow;import static java.util.stream.Collectors.toList;
List<Double> areaList = radiusList.stream().map(r -> PI * pow(r, 2)).collect(toList());...

 

注意:静态引入容易造成代码阅读困难,所以在实际项目中应该警慎使用。

 

1.9.利用 unchecked 异常

 

Java 的异常分为两类:Checked 异常和 Unchecked 异常。Unchecked 异常继承了RuntimeException ,特点是代码不需要处理它们也能通过编译,所以它们称作  Unchecked 异常。利用 Unchecked 异常,可以避免不必要的 try-catch 和 throws 异常处理。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
@Servicepublic class UserService {    public void createUser(UserCreateVO create, OpUserVO user) throws BusinessException {        checkOperatorUser(user);        ...    }    private void checkOperatorUser(OpUserVO user) throws BusinessException {        if (!hasPermission(user)) {            throw new BusinessException("用户无操作权限");        }        ...    }    ...}
@RestController@RequestMapping("/user")public class UserController {    @Autowired    private UserService userService;
    @PostMapping("/createUser")    public Result<Void> createUser(@RequestBody @Valid UserCreateVO create, OpUserVO user) throws BusinessException {        userService.createUser(create, user);        return Result.success();    }    ...}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
@Servicepublic class UserService {    public void createUser(UserCreateVO create, OpUserVO user) {        checkOperatorUser(user);        ...    }    private void checkOperatorUser(OpUserVO user) {        if (!hasPermission(user)) {            throw new BusinessRuntimeException("用户无操作权限");        }        ...    }    ...}
@RestController@RequestMapping("/user")public class UserController {    @Autowired    private UserService userService;
    @PostMapping("/createUser")    public Result<Void> createUser(@RequestBody @Valid UserCreateVO create, OpUserVO user) {        userService.createUser(create, user);        return Result.success();    }    ...}

 

 

2.利用注解


 

2.1.利用 Lombok 注解

 

Lombok 提供了一组有用的注解,可以用来消除Java类中的大量样板代码。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public class UserVO {    private Long id;    private String name;    public Long getId() {        return this.id;    }    public void setId(Long id) {        this.id = id;    }    public String getName() {        return this.name;    }    public void setName(String name) {        this.name = name;    }    ...}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
@Getter@Setter@ToStringpublic class UserVO {    private Long id;    private String name;    ...}

 

2.2.利用 Validation 注解

 

普通:


 
  •  
@Getter@Setter@ToStringpublic class UserCreateVO {    @NotBlank(message = "用户名称不能为空")    private String name;    @NotNull(message = "公司标识不能为空")    private Long companyId;    ...}@Service@Validatedpublic class UserService {    public Long createUser(@Valid UserCreateVO create) {        // TODO: 创建用户        return null;    }}

 

精简:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
@Getter@Setter@ToStringpublic class UserCreateVO {    @NotBlank(message = "用户名称不能为空")    private String name;    @NotNull(message = "公司标识不能为空")    private Long companyId;    ...}
@Service@Validatedpublic class UserService {    public Long createUser(@Valid UserCreateVO create) {        // TODO: 创建用户        return null;    }}

 

2.3.利用 @NonNull 注解

 

Spring 的 @NonNull 注解,用于标注参数或返回值非空,适用于项目内部团队协作。只要实现方和调用方遵循规范,可以避免不必要的空值判断,这充分体现了阿里的“新六脉神剑”提倡的“因为信任,所以简单”。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public List<UserVO> queryCompanyUser(Long companyId) {    // 检查公司标识    if (companyId == null) {        return null;    }
    // 查询返回用户    List<UserDO> userList = userDAO.queryByCompanyId(companyId);    return userList.stream().map(this::transUser).collect(Collectors.toList());}
Long companyId = 1L;List<UserVO> userList = queryCompanyUser(companyId);if (CollectionUtils.isNotEmpty(userList)) {    for (UserVO user : userList) {        // TODO: 处理公司用户    }}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public @NonNull List<UserVO> queryCompanyUser(@NonNull Long companyId) {    List<UserDO> userList = userDAO.queryByCompanyId(companyId);    return userList.stream().map(this::transUser).collect(Collectors.toList());}
Long companyId = 1L;List<UserVO> userList = queryCompanyUser(companyId);for (UserVO user : userList) {    // TODO: 处理公司用户}

 

2.4.利用注解特性

 

注解有以下特性可用于精简注解声明:

1、当注解属性值跟默认值一致时,可以删除该属性赋值;

2、当注解只有value属性时,可以去掉value进行简写;

3、当注解属性组合等于另一个特定注解时,直接采用该特定注解。

 

普通:

  •  
  •  
  •  
@Lazy(true);@Service(value = "userService")@RequestMapping(path = "/getUser", method = RequestMethod.GET)

 

 

精简:

  •  
  •  
  •  
@Lazy@Service("userService")@GetMapping("/getUser")

 

 

3.利用泛型


 

3.1.泛型接口

 

在 Java 没有引入泛型前,都是采用 Object 表示通用对象,最大的问题就是类型无法强校验并且需要强制类型转换。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public interface Comparable {    public int compareTo(Object other);}
@Getter@Setter@ToStringpublic class UserVO implements Comparable {    private Long id;
    @Override    public int compareTo(Object other) {        UserVO user = (UserVO)other;        return Long.compare(this.id, user.id);    }}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public interface Comparable<T> {    public int compareTo(T other);}
@Getter@Setter@ToStringpublic class UserVO implements Comparable<UserVO> {    private Long id;
    @Override    public int compareTo(UserVO other) {        return Long.compare(this.id, other.id);    }}

 

3.2.泛型类

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
@Getter@Setter@ToStringpublic class IntPoint {    private Integer x;    private Integer y;}
@Getter@Setter@ToStringpublic class DoublePoint {    private Double x;    private Double y;}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
@Getter@Setter@ToStringpublic class Point<T extends Number> {    private T x;    private T y;}

 

3.3.泛型方法

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public static Map<String, Integer> newHashMap(String[] keys, Integer[] values) {    // 检查参数非空    if (ArrayUtils.isEmpty(keys) || ArrayUtils.isEmpty(values)) {        return Collections.emptyMap();    }
    // 转化哈希映射    Map<String, Integer> map = new HashMap<>();    int length = Math.min(keys.length, values.length);    for (int i = 0; i < length; i++) {        map.put(keys[i], values[i]);    }    return map;}...

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public static <K, V> Map<K, V> newHashMap(K[] keys, V[] values) {    // 检查参数非空    if (ArrayUtils.isEmpty(keys) || ArrayUtils.isEmpty(values)) {        return Collections.emptyMap();    }
    // 转化哈希映射    Map<K, V> map = new HashMap<>();    int length = Math.min(keys.length, values.length);    for (int i = 0; i < length; i++) {        map.put(keys[i], values[i]);    }    return map;}

 

 

4.利用自身方法


 

4.1.利用构造方法

 

构造方法,可以简化对象的初始化和设置属性操作。对于属性字段较少的类,可以自定义构造方法。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
@Getter@Setter@ToStringpublic class PageDataVO<T> {    private Long totalCount;    private List<T> dataList;}
PageDataVO<UserVO> pageData = new PageDataVO<>();pageData.setTotalCount(totalCount);pageData.setDataList(userList);return pageData;

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
@Getter@Setter@ToString@NoArgsConstructor@AllArgsConstructorpublic class PageDataVO<T> {    private Long totalCount;    private List<T> dataList;}
return new PageDataVO<>(totalCount, userList);

 

注意:如果属性字段被替换时,存在构造函数初始化赋值问题。比如把属性字段title替换为 nickname ,由于构造函数的参数个数和类型不变,原有构造函数初始化语句不会报错,导致把原title值赋值给 nickname 。如果采用 Setter 方法赋值,编译器会提示错误并要求修复。

 

4.2.利用 Set 的 add 方法

 

利用 Set 的 add 方法的返回值,可以直接知道该值是否已经存在,可以避免调用 contains 方法判断存在。

 

普通:

以下案例是进行用户去重转化操作,需要先调用 contains 方法判断存在,后调用add方法进行添加。

 


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
Set<Long> userIdSet = new HashSet<>();List<UserVO> userVOList = new ArrayList<>();for (UserDO userDO : userDOList) {    if (!userIdSet.contains(userDO.getId())) {        userIdSet.add(userDO.getId());        userVOList.add(transUser(userDO));    }}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
SSet<Long> userIdSet = new HashSet<>();List<UserVO> userVOList = new ArrayList<>();for (UserDO userDO : userDOList) {    if (userIdSet.add(userDO.getId())) {        userVOList.add(transUser(userDO));    }}

 

 

4.3.利用 Map 的 computeIfAbsent 方法

 

利用 Map 的 computeIfAbsent 方法,可以保证获取到的对象非空,从而避免了不必要的空判断和重新设置值。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
Map<Long, List<UserDO>> roleUserMap = new HashMap<>();for (UserDO userDO : userDOList) {    Long roleId = userDO.getRoleId();    List<UserDO> userList = roleUserMap.get(roleId);    if (Objects.isNull(userList)) {        userList = new ArrayList<>();        roleUserMap.put(roleId, userList);    }    userList.add(userDO);}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
Map<Long, List<UserDO>> roleUserMap = new HashMap<>();for (UserDO userDO : userDOList) {    roleUserMap.computeIfAbsent(userDO.getRoleId(), key -> new ArrayList<>())        .add(userDO);}

 

4.4.利用链式编程

 

链式编程,也叫级联式编程,调用对象的函数时返回一个this对象指向对象本身,达到链式效果,可以级联调用。链式编程的优点是:编程性强、可读性强、代码简洁。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
StringBuilder builder = new StringBuilder(96);builder.append("select id, name from ");builder.append(T_USER);builder.append(" where id = ");builder.append(userId);builder.append(";");

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
StringBuilder builder = new StringBuilder(96);builder.append("select id, name from ")    .append(T_USER)    .append(" where id = ")    .append(userId)    .append(";");

 

 

5.利用工具方法


 

5.1.避免空值判断

 

普通:


 
  •  
  •  
  •  
if (userList != null && !userList.isEmpty()) {    // TODO: 处理代码}

 

精简:


 
  •  
  •  
  •  
if (CollectionUtils.isNotEmpty(userList)) {    // TODO: 处理代码}

 

5.2.避免条件判断

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
double result;if (value <= MIN_LIMIT) {    result = MIN_LIMIT;} else {    result = value;}

 

精简:


 
  •  
double result = Math.max(MIN_LIMIT, value);

 

5.3.简化赋值语句

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public static final List<String> ANIMAL_LIST;static {    List<String> animalList = new ArrayList<>();    animalList.add("dog");    animalList.add("cat");    animalList.add("tiger");    ANIMAL_LIST = Collections.unmodifiableList(animalList);}

 

精简:

  •  
  •  
  •  
  •  
// JDK流派public static final List<String> ANIMAL_LIST = Arrays.asList("dog", "cat", "tiger");// Guava流派public static final List<String> ANIMAL_LIST = ImmutableList.of("dog", "cat", "tiger");

 

注意:Arrays.asList 返回的 List 并不是 ArrayList ,不支持 add 等变更操作。

 

5.4.简化数据拷贝

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
UserVO userVO = new UserVO();userVO.setId(userDO.getId());userVO.setName(userDO.getName());...userVO.setDescription(userDO.getDescription());userVOList.add(userVO);

 

精简:


 
  •  
  •  
  •  
UserVO userVO = new UserVO();BeanUtils.copyProperties(userDO, userVO);userVOList.add(userVO);

 

反例:

  •  
List<UserVO> userVOList = JSON.parseArray(JSON.toJSONString(userDOList), UserVO.class);

 

 

精简代码,但不能以过大的性能损失为代价。例子是浅层拷贝,用不着 JSON 这样重量级的武器。

 

5.5.简化异常断言

 

普通:


 
  •  
  •  
  •  
if (Objects.isNull(userId)) {    throw new IllegalArgumentException("用户标识不能为空");}

 

精简:


 
  •  
Assert.notNull(userId, "用户标识不能为空");

 

注意:可能有些插件不认同这种判断,导致使用该对象时会有空指针警告。

 

5.6.简化测试用例

 

把测试用例数据以 JSON 格式存入文件中,通过 JSON 的 parseObject 和 parseArray 方法解析成对象。虽然执行效率上有所下降,但可以减少大量的赋值语句,从而精简了测试代码。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
@Testpublic void testCreateUser() {    UserCreateVO userCreate = new UserCreateVO();    userCreate.setName("Changyi");    userCreate.setTitle("Developer");    userCreate.setCompany("AMAP");    ...    Long userId  = userService.createUser(OPERATOR, userCreate);    Assert.assertNotNull(userId, "创建用户失败");}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
@Testpublic void testCreateUser() {    String jsonText = ResourceHelper.getResourceAsString(getClass(), "createUser.json");    UserCreateVO userCreate = JSON.parseObject(jsonText, UserCreateVO.class);    Long userId  = userService.createUser(OPERATOR, userCreate);    Assert.assertNotNull(userId, "创建用户失败");}

 

建议:JSON 文件名最好以被测试的方法命名,如果有多个版本可以用数字后缀表示。

 

5.7.简化算法实现

 

一些常规算法,已有现成的工具方法,我们就没有必要自己实现了。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
int totalSize = valueList.size();List<List<Integer>> partitionList = new ArrayList<>();for (int i = 0; i < totalSize; i += PARTITION_SIZE) {    partitionList.add(valueList.subList(i, Math.min(i + PARTITION_SIZE, totalSize)));}

 

精简:

  •  
List<List<Integer>> partitionList = ListUtils.partition(valueList, PARTITION_SIZE);

 
5.8.封装工具方法

 

一些特殊算法,没有现成的工具方法,我们就只好自己亲自实现了。

 

普通:

 

比如,SQL 设置参数值的方法就比较难用,setLong 方法不能设置参数值为 null 。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
 // 设置参数值if (Objects.nonNull(user.getId())) {  statement.setLong(1, user.getId());} else {    statement.setNull(1, Types.BIGINT);}...

 

精简:

我们可以封装为一个工具类 SqlHelper ,简化设置参数值的代码。


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
/** SQL辅助类 */public final class SqlHelper {    /** 设置长整数值 */    public static void setLong(PreparedStatement statement, int index, Long value) throws SQLException {        if (Objects.nonNull(value)) {            statement.setLong(index, value.longValue());        } else {            statement.setNull(index, Types.BIGINT);        }    }    ...}
 // 设置参数值SqlHelper.setLong(statement, 1, user.getId());

 

 

6.利用数据结构


 

6.1.利用数组简化

 

对于固定上下限范围的 if-else 语句,可以用数组+循环来简化。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public static int getGrade(double score) {    if (score >= 90.0D) {        return 1;    }    if (score >= 80.0D) {        return 2;    }    if (score >= 60.0D) {        return 3;    }    if (score >= 30.0D) {        return 4;    }    return 5;}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
private static final double[] SCORE_RANGES = new double[] {90.0D, 80.0D, 60.0D, 30.0D};public static int getGrade(double score) {    for (int i = 0; i < SCORE_RANGES.length; i++) {        if (score >= SCORE_RANGES[i]) {            return i + 1;        }    }    return SCORE_RANGES.length + 1;}

 

思考:上面的案例返回值是递增的,所以用数组简化是没有问题的。但是,如果返回值不是递增的,能否用数组进行简化呢?答案是可以的,请自行思考解决。

 

6.2.利用 Map 简化

 

对于映射关系的 if-else 语句,可以用Map来简化。此外,此规则同样适用于简化映射关系的 switch 语句。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public static String getBiologyClass(String name) {    switch (name) {        case "dog" :            return "animal";        case "cat" :            return "animal";        case "lavender" :            return "plant";        ...        default :            return null;    }}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
private static final Map<String, String> BIOLOGY_CLASS_MAP    = ImmutableMap.<String, String>builder()        .put("dog", "animal")        .put("cat", "animal")        .put("lavender", "plant")        ...        .build();public static String getBiologyClass(String name) {    return BIOLOGY_CLASS_MAP.get(name);}

 

已经把方法简化为一行代码,其实都没有封装方法的必要了。

 

6.3.利用容器类简化

 

Java 不像 Python 和 Go ,方法不支持返回多个对象。如果需要返回多个对象,就必须自定义类,或者利用容器类。常见的容器类有 Apache 的 Pair 类和 Triple 类, Pair 类支持返回 2 个对象, Triple 类支持返回 3 个对象。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
@Setter@Getter@ToString@AllArgsConstructorpublic static class PointAndDistance {    private Point point;    private Double distance;}
public static PointAndDistance getNearest(Point point, Point[] points) {    // 计算最近点和距离    ...
    // 返回最近点和距离    return new PointAndDistance(nearestPoint, nearestDistance);}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public static Pair<Point, Double> getNearest(Point point, Point[] points) {    // 计算最近点和距离    ...
    // 返回最近点和距离    return ImmutablePair.of(nearestPoint, nearestDistance);}

 

6.4.利用 ThreadLocal 简化

 

ThreadLocal 提供了线程专有对象,可以在整个线程生命周期中随时取用,极大地方便了一些逻辑的实现。用 ThreadLocal 保存线程上下文对象,可以避免不必要的参数传递。

 

普通:

由于 DateFormat 的 format 方法线程非安全(建议使用替代方法),在线程中频繁初始化 DateFormat 性能太低,如果考虑重用只能用参数传入 DateFormat 。例子如下:

 


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public static String formatDate(Date date, DateFormat format) {    return format.format(date);}
public static List<String> getDateList(Date minDate, Date maxDate, DateFormat format) {    List<String> dateList = new ArrayList<>();    Calendar calendar = Calendar.getInstance();    calendar.setTime(minDate);    String currDate = formatDate(calendar.getTime(), format);    String maxsDate = formatDate(maxDate, format);    while (currDate.compareTo(maxsDate) <= 0) {        dateList.add(currDate);        calendar.add(Calendar.DATE, 1);        currDate = formatDate(calendar.getTime(), format);    }    return dateList;}

 

精简:

可能你会觉得以下的代码量反而多了,如果调用工具方法的地方比较多,就可以省下一大堆 DateFormat 初始化和传入参数的代码。


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
private static final ThreadLocal<DateFormat> LOCAL_DATE_FORMAT = new ThreadLocal<DateFormat>() {    @Override    protected DateFormat initialValue() {        return new SimpleDateFormat("yyyyMMdd");    }};
public static String formatDate(Date date) {    return LOCAL_DATE_FORMAT.get().format(date);}
public static List<String> getDateList(Date minDate, Date maxDate) {    List<String> dateList = new ArrayList<>();    Calendar calendar = Calendar.getInstance();    calendar.setTime(minDate);    String currDate = formatDate(calendar.getTime());    String maxsDate = formatDate(maxDate);    while (currDate.compareTo(maxsDate) <= 0) {        dateList.add(currDate);        calendar.add(Calendar.DATE, 1);        currDate = formatDate(calendar.getTime());    }    return dateList;}

 

注意:ThreadLocal 有一定的内存泄露的风险,尽量在业务代码结束前调用 remove 方法进行数据清除。

 

 

7.利用 Optional


 

在 Java 8 里,引入了一个 Optional 类,该类是一个可以为 null 的容器对象。

 

7.1.保证值存在

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
Integer thisValue;if (Objects.nonNull(value)) {    thisValue = value;} else {    thisValue = DEFAULT_VALUE;}

 

精简:

  •  
Integer thisValue = Optional.ofNullable(value).orElse(DEFAULT_VALUE);

 

7.2.保证值合法

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
Integer thisValue;if (Objects.nonNull(value) && value.compareTo(MAX_VALUE) <= 0) {    thisValue = value;} else {    thisValue = MAX_VALUE;}

 

精简:


 

 

  •  
  •  
Integer thisValue = Optional.ofNullable(value)    .filter(tempValue -> tempValue.compareTo(MAX_VALUE) <= 0).orElse(MAX_VALUE);

 
7.3.避免空判断

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
String zipcode = null;if (Objects.nonNull(user)) {    Address address = user.getAddress();    if (Objects.nonNull(address)) {        Country country = address.getCountry();        if (Objects.nonNull(country)) {            zipcode = country.getZipcode();        }    }}


精简:

  •  
  •  
tring zipcode = Optional.ofNullable(user).map(User::getAddress)    .map(Address::getCountry).map(Country::getZipcode).orElse(null);

 

 

8.利用 Stream


 

流(Stream)是Java 8的新成员,允许你以声明式处理数据集合,可以看成为一个遍历数据集的高级迭代器。流主要有三部分构成:获取一个数据源→数据转换→执行操作获取想要的结果。每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象,这就允许对其操作可以像链条一样排列,形成了一个管道。流(Stream)提供的功能非常有用,主要包括匹配、过滤、汇总、转化、分组、分组汇总等功能。

 

8.1.匹配集合数据

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
boolean isFound = false;for (UserDO user : userList) {    if (Objects.equals(user.getId(), userId)) {        isFound = true;        break;    }}

 

精简:


 
  •  
  •  
boolean isFound = userList.stream()    .anyMatch(user -> Objects.equals(user.getId(), userId));

 

8.2.过滤集合数据

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
List<UserDO> resultList = new ArrayList<>();for (UserDO user : userList) {    if (Boolean.TRUE.equals(user.getIsSuper())) {        resultList.add(user);    }}

 

精简:


 
  •  
  •  
  •  
List<UserDO> resultList = userList.stream()    .filter(user -> Boolean.TRUE.equals(user.getIsSuper()))    .collect(Collectors.toList());

 

8.3.汇总集合数据

 

普通:


 
  •  
  •  
  •  
  •  
double total = 0.0D;for (Account account : accountList) {    total += account.getBalance();}

 

精简:

  •  
double total = accountList.stream().mapToDouble(Account::getBalance).sum();

 
8.4.转化集合数据

 
普通:

 
  •  
  •  
  •  
  •  
List<UserVO> userVOList = new ArrayList<>();for (UserDO userDO : userDOList) {    userVOList.add(transUser(userDO));}

 

精简:


 
  •  
  •  
List<UserVO> userVOList = userDOList.stream()    .map(this::transUser).collect(Collectors.toList());

 

8.5.分组集合数据

 

普通:


 
  •  
  •  
  •  
  •  
  •  
Map<Long, List<UserDO>> roleUserMap = new HashMap<>();for (UserDO userDO : userDOList) {    roleUserMap.computeIfAbsent(userDO.getRoleId(), key -> new ArrayList<>())        .add(userDO);}

 

精简:


 
  •  
  •  
Map<Long, List<UserDO>> roleUserMap = userDOList.stream()    .collect(Collectors.groupingBy(UserDO::getRoleId));


8.6.分组汇总集合

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
Map<Long, Double> roleTotalMap = new HashMap<>();for (Account account : accountList) {    Long roleId = account.getRoleId();    Double total = Optional.ofNullable(roleTotalMap.get(roleId)).orElse(0.0D);    roleTotalMap.put(roleId, total + account.getBalance());}

 

精简:

  •  
roleTotalMap = accountList.stream().collect(Collectors.groupingBy(Account::getRoleId, Collectors.summingDouble(Account::getBalance)));

 
8.7.生成范围集合

 

Python 的 range 非常方便,Stream 也提供了类似的方法。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
int[] array1 = new int[N];for (int i = 0; i < N; i++) {    array1[i] = i + 1;}
int[] array2 = new int[N];array2[0] = 1;for (int i = 1; i < N; i++) {    array2[i] = array2[i - 1] * 2;}

 

精简:


 
  •  
  •  
int[] array1 = IntStream.rangeClosed(1, N).toArray();int[] array2 = IntStream.iterate(1, n -> n * 2).limit(N).toArray();

 

 

9.利用程序结构


 

9.1.返回条件表达式

 

条件表达式判断返回布尔值,条件表达式本身就是结果。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public boolean isSuper(Long userId)    UserDO user = userDAO.get(userId);    if (Objects.nonNull(user) && Boolean.TRUE.equals(user.getIsSuper())) {        return true;    }    return false;}


精简:


 
  •  
  •  
  •  
  •  
public boolean isSuper(Long userId)    UserDO user = userDAO.get(userId);    return Objects.nonNull(user) && Boolean.TRUE.equals(user.getIsSuper());}

 

9.2.最小化条件作用域

 

最小化条件作用域,尽量提出公共处理代码。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
Result result = summaryService.reportWorkDaily(workDaily);if (result.isSuccess()) {    String message = "上报工作日报成功";    dingtalkService.sendMessage(user.getPhone(), message);} else {    String message = "上报工作日报失败:" + result.getMessage();    log.warn(message);    dingtalkService.sendMessage(user.getPhone(), message);}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
String message;Result result = summaryService.reportWorkDaily(workDaily);if (result.isSuccess()) {    message = "上报工作日报成功";} else {    message = "上报工作日报失败:" + result.getMessage();    log.warn(message);}dingtalkService.sendMessage(user.getPhone(), message);

 

9.3.调整表达式位置

 

调整表达式位置,在逻辑不变的前提下,让代码变得更简洁。

 

普通1:


 
  •  
  •  
  •  
  •  
  •  
String line = readLine();while (Objects.nonNull(line)) {    ... // 处理逻辑代码    line = readLine();}


普通2:


 
  •  
  •  
  •  
for (String line = readLine(); Objects.nonNull(line); line = readLine()) {    ... // 处理逻辑代码}


精简:


 
  •  
  •  
  •  
  •  
String line;while (Objects.nonNull(line = readLine())) {    ... // 处理逻辑代码}


注意:有些规范可能不建议这种精简写法。

 

9.4.利用非空对象

 

在比较对象时,交换对象位置,利用非空对象,可以避免空指针判断。

 

普通:


 
  •  
  •  
  •  
private static final int MAX_VALUE = 1000;boolean isMax = (value != null && value.equals(MAX_VALUE));boolean isTrue = (result != null && result.equals(Boolean.TRUE));

 

精简:


 
  •  
  •  
  •  
private static final Integer MAX_VALUE = 1000;boolean isMax = MAX_VALUE.equals(value);boolean isTrue = Boolean.TRUE.equals(result);

 

 

10.利用设计模式


 

10.1.模板方法模式

 

模板方法模式(Template Method Pattern)定义一个固定的算法框架,而将算法的一些步骤放到子类中实现,使得子类可以在不改变算法框架的情况下重定义该算法的某些步骤。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
@Repositorypublic class UserValue {    /** 值操作 */    @Resource(name = "stringRedisTemplate")    private ValueOperations<String, String> valueOperations;    /** 值模式 */    private static final String KEY_FORMAT = "Value:User:%s";
    /** 设置值 */    public void set(Long id, UserDO value) {        String key = String.format(KEY_FORMAT, id);        valueOperations.set(key, JSON.toJSONString(value));    }
    /** 获取值 */    public UserDO get(Long id) {        String key = String.format(KEY_FORMAT, id);        String value = valueOperations.get(key);        return JSON.parseObject(value, UserDO.class);    }
    ...}
@Repositorypublic class RoleValue {    /** 值操作 */    @Resource(name = "stringRedisTemplate")    private ValueOperations<String, String> valueOperations;    /** 值模式 */    private static final String KEY_FORMAT = "Value:Role:%s";
    /** 设置值 */    public void set(Long id, RoleDO value) {        String key = String.format(KEY_FORMAT, id);        valueOperations.set(key, JSON.toJSONString(value));    }
    /** 获取值 */    public RoleDO get(Long id) {        String key = String.format(KEY_FORMAT, id);        String value = valueOperations.get(key);        return JSON.parseObject(value, RoleDO.class);    }
    ...}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public abstract class AbstractDynamicValue<I, V> {    /** 值操作 */    @Resource(name = "stringRedisTemplate")    private ValueOperations<String, String> valueOperations;
    /** 设置值 */    public void set(I id, V value) {        valueOperations.set(getKey(id), JSON.toJSONString(value));    }
    /** 获取值 */    public V get(I id) {        return JSON.parseObject(valueOperations.get(getKey(id)), getValueClass());    }
    ...
    /** 获取主键 */    protected abstract String getKey(I id);
    /** 获取值类 */    protected abstract Class<V> getValueClass();}
@Repositorypublic class UserValue extends AbstractValue<Long, UserDO> {    /** 获取主键 */    @Override    protected String getKey(Long id) {        return String.format("Value:User:%s", id);    }
    /** 获取值类 */    @Override    protected Class<UserDO> getValueClass() {        return UserDO.class;    }}
@Repositorypublic class RoleValue extends AbstractValue<Long, RoleDO> {    /** 获取主键 */    @Override    protected String getKey(Long id) {        return String.format("Value:Role:%s", id);    }
    /** 获取值类 */    @Override    protected Class<RoleDO> getValueClass() {        return RoleDO.class;    }}

 

10.2.建造者模式

 

建造者模式(Builder Pattern)将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public interface DataHandler<T> {    /** 解析数据 */public T parseData(Record record);
    /** 存储数据 */public boolean storeData(List<T> dataList);}
public <T> long executeFetch(String tableName, int batchSize, DataHandler<T> dataHandler) throws Exception {    // 构建下载会话    DownloadSession session = buildSession(tableName);
    // 获取数据数量    long recordCount = session.getRecordCount();    if (recordCount == 0) {        return 0;    }
    // 进行数据读取    long fetchCount = 0L;    try (RecordReader reader = session.openRecordReader(0L, recordCount, true)) {        // 依次读取数据        Record record;        List<T> dataList = new ArrayList<>(batchSize);        while ((record = reader.read()) != null) {            // 解析添加数据            T data = dataHandler.parseData(record);            if (Objects.nonNull(data)) {                dataList.add(data);            }
            // 批量存储数据            if (dataList.size() == batchSize) {                boolean isContinue = dataHandler.storeData(dataList);                fetchCount += batchSize;                dataList.clear();                if (!isContinue) {                    break;                }            }        }
        // 存储剩余数据        if (CollectionUtils.isNotEmpty(dataList)) {            dataHandler.storeData(dataList);            fetchCount += dataList.size();            dataList.clear();        }    }
    // 返回获取数量    return fetchCount;}
 // 使用案例long fetchCount = odpsService.executeFetch("user", 5000, new DataHandler() {    /** 解析数据 */    @Overridepublic T parseData(Record record) {        UserDO user = new UserDO();        user.setId(record.getBigint("id"));        user.setName(record.getString("name"));        return user;    }
    /** 存储数据 */    @Overridepublic boolean storeData(List<T> dataList) {        userDAO.batchInsert(dataList);        return true;    }});

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public <T> long executeFetch(String tableName, int batchSize, Function<Record, T> dataParser, Function<List<T>, Boolean> dataStorage) throws Exception {    // 构建下载会话    DownloadSession session = buildSession(tableName);
    // 获取数据数量    long recordCount = session.getRecordCount();    if (recordCount == 0) {        return 0;    }
    // 进行数据读取    long fetchCount = 0L;    try (RecordReader reader = session.openRecordReader(0L, recordCount, true)) {        // 依次读取数据        Record record;        List<T> dataList = new ArrayList<>(batchSize);        while ((record = reader.read()) != null) {            // 解析添加数据            T data = dataParser.apply(record);            if (Objects.nonNull(data)) {                dataList.add(data);            }
            // 批量存储数据            if (dataList.size() == batchSize) {                Boolean isContinue = dataStorage.apply(dataList);                fetchCount += batchSize;                dataList.clear();                if (!Boolean.TRUE.equals(isContinue)) {                    break;                }            }        }
        // 存储剩余数据        if (CollectionUtils.isNotEmpty(dataList)) {            dataStorage.apply(dataList);            fetchCount += dataList.size();            dataList.clear();        }    }
    // 返回获取数量    return fetchCount;}
 // 使用案例long fetchCount = odpsService.executeFetch("user", 5000, record -> {        UserDO user = new UserDO();        user.setId(record.getBigint("id"));        user.setName(record.getString("name"));        return user;    }, dataList -> {        userDAO.batchInsert(dataList);        return true;    });

 

普通的建造者模式,实现时需要定义 DataHandler 接口,调用时需要实现 DataHandler 匿名内部类,代码较多较繁琐。而精简后的建造者模式,充分利用了函数式编程,实现时无需定义接口,直接使用 Function 接口;调用时无需实现匿名内部类,直接采用 lambda 表达式,代码较少较简洁。

 

10.3.代理模式

 

Spring 中最重要的代理模式就是 AOP (Aspect-Oriented Programming,面向切面的编程),是使用 JDK 动态代理和 CGLIB 动态代理技术来实现的。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
@Slf4j@RestController@RequestMapping("/user")public class UserController {    /** 用户服务 */    @Autowired    private UserService userService;
    /** 查询用户 */    @PostMapping("/queryUser")    public Result<?> queryUser(@RequestBody @Valid UserQueryVO query) {        try {            PageDataVO<UserVO> pageData = userService.queryUser(query);            return Result.success(pageData);        } catch (Exception e) {            log.error(e.getMessage(), e);            return Result.failure(e.getMessage());        }    }    ...}

 

精简1:

 

基于  @ControllerAdvice 的异常处理:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
@RestController@RequestMapping("/user")public class UserController {    /** 用户服务 */    @Autowired    private UserService userService;
    /** 查询用户 */    @PostMapping("/queryUser")    public Result<PageDataVO<UserVO>> queryUser(@RequestBody @Valid UserQueryVO query) {        PageDataVO<UserVO> pageData = userService.queryUser(query);        return Result.success(pageData);    }    ...}
@Slf4j@ControllerAdvicepublic class GlobalControllerAdvice {    /** 处理异常 */    @ResponseBody    @ExceptionHandler(Exception.class)    public Result<Void> handleException(Exception e) {        log.error(e.getMessage(), e);        return Result.failure(e.getMessage());    }}

 

精简2:

 

基于 AOP 的异常处理:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
// UserController代码同"精简1"
@Slf4j@Aspectpublic class WebExceptionAspect {    /** 点切面 */    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")    private void webPointcut() {}
    /** 处理异常 */    @AfterThrowing(pointcut = "webPointcut()", throwing = "e")    public void handleException(Exception e) {        Result<Void> result = Result.failure(e.getMessage());        writeContent(JSON.toJSONString(result));    }    ...}

 

 

11.利用删除代码


 

“少即是多”,“少”不是空白而是精简,“多”不是拥挤而是完美。删除多余的代码,才能使代码更精简更完美。

 

11.1.删除已废弃的代码

 

删除项目中的已废弃的包、类、字段、方法、变量、常量、导入、注解、注释、已注释代码、Maven包导入、MyBatis的SQL语句、属性配置字段等,可以精简项目代码便于维护。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
import lombok.extern.slf4j.Slf4j;@Slf4j@Servicepublic class ProductService {    @Value("discardRate")    private double discardRate;    ...    private ProductVO transProductDO(ProductDO productDO) {        ProductVO productVO = new ProductVO();        BeanUtils.copyProperties(productDO, productVO);        // productVO.setPrice(getDiscardPrice(productDO.getPrice()));        return productVO;    }    private BigDecimal getDiscardPrice(BigDecimal originalPrice) {        ...    }}

 

精简:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
@Servicepublic class ProductService {    ...    private ProductVO transProductDO(ProductDO productDO) {        ProductVO productVO = new ProductVO();        BeanUtils.copyProperties(productDO, productVO);        return productVO;    }}11.2.删除接口方法的public对于接口(interface),所有的字段和方法都是public的,可以不用显式声明为public。普通:public interface UserDAO {    public Long countUser(@Param("query") UserQuery query);    public List<UserDO> queryUser(@Param("query") UserQuery query);}

 

 

11.2.删除接口方法的public

 

对于接口(interface),所有的字段和方法都是 public 的,可以不用显式声明为 public 。

 

普通:


 
  •  
  •  
  •  
  •  
public interface UserDAO {    public Long countUser(@Param("query") UserQuery query);    public List<UserDO> queryUser(@Param("query") UserQuery query);}

 

精简:


 
  •  
  •  
  •  
  •  
public interface UserDAO {    Long countUser(@Param("query") UserQuery query);    List<UserDO> queryUser(@Param("query") UserQuery query);}

 

11.3.删除枚举构造方法的 private

 

对于枚举(menu),构造方法都是 private 的,可以不用显式声明为 private 。

 

普通:


 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public enum UserStatus {    DISABLED(0, "禁用"),    ENABLED(1, "启用");  private final Integer value;    private final String desc;    private UserStatus(Integer value, String desc) {        this.value = value;        this.desc = desc;    }    ...}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public enum UserStatus {    DISABLED(0, "禁用"),    ENABLED(1, "启用");    private final Integer value;    private final String desc;    UserStatus(Integer value, String desc) {        this.value = value;        this.desc = desc;    }    ...}

 

11.4.删除 final 类方法的 final

 

对于 final 类,不能被子类继承,所以其方法不会被覆盖,没有必要添加 final 修饰。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public final Rectangle implements Shape {    ...    @Override    public final double getArea() {        return width * height;    }}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public final Rectangle implements Shape {    ...    @Override    public double getArea() {        return width * height;    }}

 

11.5.删除基类 implements 的接口

 

如果基类已 implements 某接口,子类没有必要再 implements 该接口,只需要直接实现接口方法即可。

 

普通:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public interface Shape {    ...    double getArea();}public abstract AbstractShape implements Shape {    ...}public final Rectangle extends AbstractShape implements Shape {    ...    @Override    public double getArea() {        return width * height;    }}

 

精简:


 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
...public final Rectangle extends AbstractShape {    ...    @Override    public double getArea() {        return width * height;    }}

 

11.6.删除不必要的变量

 

不必要的变量,只会让代码看起来更繁琐。

 

普通:


 
  •  
  •  
  •  
  •  
public Boolean existsUser(Long userId) {    Boolean exists = userDAO.exists(userId);    return exists;}

 

精简:


 
  •  
  •  
  •  
public Boolean existsUser(Long userId) {    return userDAO.exists(userId);}

 

 

后记


 

古语又云:

有道无术,术尚可求也;有术无道,止于术。

意思是:有“道”而无“术”,“术”还可以逐渐获得;有“术”而无“道”,就可能止步于“术”了。所以,我们不要仅满足于从实践中总结“术”,因为“道”的表现形式是多变的;而应该上升到“道”的高度,因为“术”背后的道理是相通的。当遇到新的事物时,我们可以从理论中找到“道”、从实践中找出“术”,尝试着去认知新的事物。

light-java是一个快速轻量级和更高效的Java微服务框架 light-java是内置了undertow http服务器的REST微服务轻量Java框架,它比Spring Boot内嵌Tomcat这样流行的微服务平台要快44倍,与Go语言fast-http性能接近。 立即下载

相关推荐

Dr Java,轻量级Java编译器

DrJava is a lightweight development environment for writing Java programs. It is designed primarily for students, providing an intuitive interface and the ability to interactively evaluate Java code. It also includes powerful features for more advanced users. DrJava is available for free under the BSD License, and it is under active development by the JavaPLT group at Rice University.

Java 代码精简之道

古语有云: 道为术之灵,术为道之体;以道统术,以术得道。 其中:“道”指“规律、道理、理论”,“术”指“方法、技巧、技术”。意思是:“道”是“术”的灵魂,“术”是“道”的肉体;可以用“道”来统管“术”,也可以从“术”中获得“道”。 在拜读大佬“孤尽”的文章《Code Review是苦涩但有意思的修行》时,感受最深的一句话就是:“优质的代码一定是少即是多的精兵原则”,这就是大佬的代码精简之...

javaboy 3399

用notepad++ 打造轻量级Java c编译器

使用Notepad++和gcc在WIN7搭建C语言环境 用notepad++ 打造轻量级Java编译器

JDK8新特性

JDK8是Java升级变化最大的一个版本,JDK8引入很多新的写法,比如函数式接口、Lambda表达式、Stream函数式操作流元素集合、接口的默认方法、接口的静态方法等。JDK8是Java升级变化最大的一个版本,JDK8引入很多新的写法,比如函数式接口、Lambda表达式、Stream函数式操作流元素集合、接口的默认方法、接口的静态方法等。

Qt+OpenGL+Cesium三件套:打造高性能3D GIS界面的5个关键技巧

本文深入探讨了如何利用Qt、OpenGL与Cesium三件套打造高性能3D GIS界面的5个核心技巧。内容涵盖多线程渲染架构设计、OpenGL状态管理与批处理优化、内存与显存高效管理、Qt UI与3D场景深度集成,以及跨平台部署与性能调优实战,旨在帮助开发者解决海量3D Tiles数据渲染的性能瓶颈,实现流畅的交互体验。

t8u9v0的博客 551

别再死记硬背了!用51单片机的AD/DA和PWM,亲手做个简易示波器信号发生器

本文详细介绍了如何利用51单片机的PWM和AD/DA功能制作简易示波器信号发生器。通过PWM模拟DAC输出波形,结合XPT2046 ADC进行信号测量,实现方波、三角波和正弦波的生成与显示。项目不仅成本低廉,还能帮助电子爱好者深入理解51单片机的核心功能,是理论与实践结合的绝佳案例。

weixin_28675839的博客 265

总结了大量的 Java 代码精简之道,值得一看

转载自品略图书馆http://www.pinlue.com/article/2020/06/3022/0910903417432.html Java 代码精简之“道”。 1.利用语法 1.1.利用三元表达式 普通: String title;if (isMember(phone)) { title = "会员";} else { title = "游客";} 精简: String title = isMem...

yihuliunian的博客 377

基于 Cognex VisionPro 的工业级图像匹配技术全解析

通过本文的深度解析,开发者可以系统掌握 Cognex VisionPro 图像匹配技术的核心原理、开发流程、优化策略及工业级应用。实际项目中,需结合具体场景灵活调整参数,综合运用预处理、特征提取和匹配算法,构建稳定可靠的视觉系统。

品质生活,极致编程。 1596

简洁Java之道

计算机专家在问题求解时非常重视表达式简洁性的价值。Unix的先驱者Ken Thompson曾经说过非常著名的一句话:“丢弃1000行代码的那一天是我最有成效的一天之一。”这对于任何一个需要持续支持和维护的软件项目来说,都是一个当之无愧的目标。早期的Lisp贡献者Paul Graham甚至将语言的简洁性等同为语言的能力。这种对能力的认识让可以编写紧凑、简介的代码成为许多现代软件项目选择语言的首要标准

feilex的专栏 920

拆解大疆M300电池BMS:基于TI TIDA-010030方案的硬件架构深度分析

本文深度解析了大疆M300无人机电池管理系统(BMS)基于TI TIDA-010030参考设计的硬件架构。通过对比TI方案与大疆实现的差异,详细介绍了BQ7694003监控前端和BQ34Z100电量计的优化设计,以及通信架构的可靠性改进。文章还揭示了大疆在成本、空间和标准化方面的工程妥协与创新平衡,为锂电池保护方案提供了实践参考。

weixin_27066963的博客 240

用VASP计算GW+BSE

VASP在5.3以后的版本都能用解BSE方程的方法,在计算光吸收的过程中考虑激子效应。 下面就来写一个用BSE计算bulkSi的例子 首先,介电函数的计算是在GW计算的基础之上的。这里首先介绍G0W0的计算(我们这里直接在PBE的波函数基础上进行G0W0计算)。 1.PBE自恰计算,写WAVECAR System= Silicon groundstate occupied

ultra1989的专栏 2万+

Java 代码精简之道,总结得太好了!

Java技术栈www.javastack.cn打开网站看更多优质文章前言古语有云:道为术之灵,术为道之体;以道统术,以术得道。其中:“道”指“规律、道理、理论”,“术”指“方法、技巧、技...

Java技术栈,分享最主流的Java技术 732

手把手教你学Simulink——基于Simulink的前馈解耦SVPWM整流器仿真

本文详细介绍了基于Simulink的前馈解耦SVPWM整流器仿真方法。针对三相PWM整流器存在的dq轴交叉耦合问题,提出前馈解耦控制方案,通过在电流环中引入耦合电压补偿项,显著提升系统性能。文章包含完整的系统架构、核心算法、Simulink建模步骤及参数设置,仿真结果显示:电流跟踪误差<2%、动态响应时间<0.05s、THD<3%、功率因数>0.999。同时提供了可直接复用的MATLAB代码和工程优化建议,为电力电子工程师实现高精度AC/DC转换提供了实用解决方案。

MHD0815的博客 108

java代码_Java 代码精简之道

作者 |常意来源 |阿里巴巴中间件(ID:Aliware_2018)古语有云:道为术之灵,术为道之体;以道统术,以术得道。其中:“道”指“规律、道理、理论”,“术”指“方法、技巧、技术”。意思是:“道”是“术”的灵魂,“术”是“道”的肉体;可以用“道”来统管“术”,也可以从“术”中获得“道”。在拜读大佬“孤尽”的文章《Code Review是苦涩但有意思的修行》时,感受最深的一句...

weixin_39684995的博客 2660

Allegro Design Entry HDL(OrCAD Capture HDL)原理图是设计快速入门图文教程

Allegro Design Entry HDL是Cadence公司开发的原理图设计工具,也可与Allegro PCB设计工具无缝对接,虽然板级开发中不如Design Entry CIS(又名 OrCAD Capture CIS)的使用那么广泛,但是由于Design Entry HDL支持芯片的开发,所以有不少公司尤其是芯片背景公司,选择使用Design Entry HDL进行原理图设计。两个原理图开发工具的使用方法大同小异,本文简单介绍使用Allegro Design Entry HDL开始一个新的设计,

fydar的博客 4134

YOLOv9分割改进 ,YOLOv9分割改进主干网络为华为EfficientNet,助力涨点

EfficientNet论文中研究了卷积网络的缩放和,并证明对深度,宽度和分辨率复合缩放的重要性,因此精度和效率更好。为了阐述相关的原理,我们提出了简单有效的复合缩放方法,使得模型缩放具有一定设计准则,同时兼顾了模型的效率。我下文将 YOLOv9 分割模型改进主干网络为 EfficientNet 融合网络结构。论文地址代码地址下文都是手把手教程,跟着操作即可添加成功把环境配置好,数据集处理好,训练基本能成功,创作不易,请帮忙点一个爱心,关注我,带你不挂科!

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 942

Java代码精简之道

前言 古语有云: 道为术之灵,术为道之体;以道统术,以术得道。 其中:“道”指“规律、道理、理论”,“术”指“方法、技巧、技术”。意思是:“道”是“术”的灵魂,“术”是“道”的肉体;可以用“道”来统管“术”,也可以从“术”中获得“道”。 在拜读大佬“孤尽”的文章《Code Review是苦涩但有意思的修行》时,感受最深的一句话就是:“优质的代码一定是少即是多的精兵原则”,这就是大佬的代码精简之“道”。 工匠追求“术”到极致,其实就是在寻“道”,且离悟“道”也就不远了,亦或是已经得道,这就是“工

阿里云云栖号 1295

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

道指mt4代码_Java 代码精简之道

作者 |常意来源 |阿里巴巴中间件(ID:Aliware_2018)古语有云:道为术之灵,术为道之体;以道统术,以术得道。其中:“道”指“规律、道理、理论”,“术”指“方法、技巧、技术”。意思是:“道”是“术”的灵魂,“术”是“道”的肉体;可以用“道”来统管“术”,也可以从“术”中获得“道”。在拜读大佬“孤尽”的文章《Code Review是苦涩但有意思的修行》时,感受最深的一句...

weixin_40008644的博客 418

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

上一篇: Java 10 大装 B 写法,看完可以出去吹牛逼了!
下一篇: Spring Boot 把 Maven 干掉了,正式拥抱 Gradle!
Java奥利给
博客等级 码龄6年 150粉丝 154原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值