⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 blog.csdn.net/qq_30285985/article/details/112849366 「叁滴水」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

前言

项目开发中,常有一些标识的使用,<男,女>、<正常,删除>等等。这些信息在数据库中会以某种标识符进行保存,但是这些标识符在代码中如何呈现,每个开发者都有一套自己的习惯,这种个性化习惯在大型项目开发时可能会因代码规范问题导致严重bug,在此,笔者阐述下在开发过程中的解决思路,使得代码更加具有可读性,请大家参考。

一、常见写法弊端展示

1.1、字符串匹配

在开发时将<男,女>转换为<1,2>,然后在项目组开发时互相转达这样的对应关系,就出现了如下代码。

//如果sex是字符串,java中可以通过==对比值吗?
if(user.getSex () == "1"){
//todo 如果是男生
}
//Sex 是字符串类型eq方法中传入1会返回true吗?
if(user.getSex ().equals (1)){
//todo 如果是男生
}

如上代码的弊端如下:

  1. user一定是对象一定是被实例化后的吗?如果user是null的话,直接使用会报空指针异常。
  2. 字符串直接==比对不是比对的Value。相信学习java时就会重点说明,但是不巧,开发中我也见过有这种写法。
  3. 字符串通过eq方法比对值一般是没有问题的,但是字符串类型的eq方法里传入的是一个Object类型的值,因此,即使传入一个数值类型也不会编译错误。如果误写成“1”.equals(1)将永远返回false。因此这种不容易发现的问题,常常导致严重的bug。

public static void main (String[] args)
{
String man = "1";
Integer sex = 1;
System.out.println (man.equals (sex));
//输出
//false
}

另外,项目中直接通过字符串匹配,代码的可读性也会变差。多人开发的时候又有谁能够保证你说的状态1(String)和我说的状态1(Integer)是同一个1呢。

1.2、数值匹配

上面列举了字符串匹配,数值匹配同样也有容易出问题的写法。

public static void main (String[] args)
{
Integer man = 200;
Integer sex = 200;
System.out.println (man==sex);
Integer man1 = 2;
Integer sex1 = 2;
System.out.println (man1==sex1);
}
// false
// true

如上这种相同的写法,却有不同的返回值,这种就很诡异。原因就在Integer.valueOf方法中。

public static Integer valueOf(int i) {
//low = -128
// high = 127
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

因此,当比对的数值在[-128,127]的范围中,通过==对比会返回true,否则返回false,所以如果调用接口时,返回的状态码是数值型的200的时候,判断就需要注意一下。

另外,Integer也有eq方法,与String类型一样,传入Object类型,Integer.equals("1")也不会编译报错。

二、代码优化

2.1、枚举对应数据库字段

例如如上定义,通过表明+Enum定义java类名,类中通过枚举对应到数据库的字段,这样可以在多人开发时避免出现状态码定位不一致问题,从而使得代码有一个良好的可读性。

import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.HashMap;
public class UserEnum
{
@Getter
@AllArgsConstructor
public enum Sex{
Man(1,"男"),WOMAN(2,"女");
public Integer code;
public String msg;

private static HashMap<Integer,Sex> data = new HashMap<Integer,Sex>();
static {
for(Sex d : Sex.values()){
data.put(d.code, d);
}
}
public static Sex parse(Integer code) {
if(data.containsKey(code)){
return data.get(code);
}
return null;
}
}
//按照如上写法,同样可以有 状态码:正常,禁用,删除
//public enum Status
// 角色:管理员,普通用户
//public enum role
}

2.2、数值转换枚举

在开发接口给前端开发时,前端会传入数值类型的状态,这时需要与对应的枚举类型进行转换。

代码如下:

public static void main (String[] args)
{
//此处假如客户端传入状态码 1
Integer man =1;
UserEnum.Sex parse = UserEnum.Sex.parse (man);
System.out.println (parse);
}

2.3、枚举使用switch

public static void main (String[] args)
{
//此处假如客户端传入状态码 1
Integer man =1;
UserEnum.Sex parse = UserEnum.Sex.parse (man);
switch (parse){
case Man:
//todo
break;
case WOMAN:
//todo
break;
}
}

2.4、枚举状态机

虽然常有项目组通过常量来使得代码更加规范,但是通过枚举可以在多状态转换的场景下使得代码更加友好的呈现。

在一个请假单的审批过程中肯定有这几种状态<发起审批,组长审批,经理审批,人事备案>。状态机代码示例:

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
//审批状态码
public enum ApprovalStatusEnum
{

START(1,"开始审批"){
@Override
ApprovalStatusEnum getNextStatus ()
{
return first_leader;
}
},
first_leader(2,"第一个领导审批"){
@Override
ApprovalStatusEnum getNextStatus ()
{
return second_leader;
}
},
second_leader(3,"第二个领导审批"){
@Override
ApprovalStatusEnum getNextStatus ()
{
return backups;
}
},
backups(4,"备案"){
@Override
ApprovalStatusEnum getNextStatus ()
{
return null;
}
};

private Integer code;
private String msg;

abstract ApprovalStatusEnum getNextStatus();
}

在枚举类中定义抽象方法,并且在每个状态中进行具体的实现。如此在有大量的状态转移的场景中(固定的审批场景,支付场景),当前状态调用nextStatus()方法获取下一个状态。这种写法可以使得代码更加简洁干净,更加便于维护。

文章目录
  1. 1. 前言
  2. 2. 一、常见写法弊端展示
    1. 2.1. 1.1、字符串匹配
    2. 2.2. 1.2、数值匹配
  3. 3. 二、代码优化
    1. 3.1. 2.1、枚举对应数据库字段
    2. 3.2. 2.2、数值转换枚举
    3. 3.3. 2.3、枚举使用switch
    4. 3.4. 2.4、枚举状态机