如何優(yōu)雅的使用枚舉
作者:叁滴水
blog.csdn.net/qq_30285985/article/details/112849366
前言
項(xiàng)目開發(fā)中,常有一些標(biāo)識(shí)的使用,<男,女>、<正常,刪除>等等。這些信息在數(shù)據(jù)庫(kù)中會(huì)以某種標(biāo)識(shí)符進(jìn)行保存,但是這些標(biāo)識(shí)符在代碼中如何呈現(xiàn),每個(gè)開發(fā)者都有一套自己的習(xí)慣,這種個(gè)性化習(xí)慣在大型項(xiàng)目開發(fā)時(shí)可能會(huì)因代碼規(guī)范問(wèn)題導(dǎo)致嚴(yán)重bug,在此,筆者闡述下在開發(fā)過(guò)程中的解決思路,使得代碼更加具有可讀性,請(qǐng)大家參考。
一、常見寫法弊端展示
1.1、字符串匹配
在開發(fā)時(shí)將<男,女>轉(zhuǎn)換為<1,2>,然后在項(xiàng)目組開發(fā)時(shí)互相轉(zhuǎn)達(dá)這樣的對(duì)應(yīng)關(guān)系,就出現(xiàn)了如下代碼。
//如果sex是字符串,java中可以通過(guò)==對(duì)比值嗎?
if(user.getSex () == "1"){
//todo 如果是男生
}
//Sex 是字符串類型eq方法中傳入1會(huì)返回true嗎?
if(user.getSex ().equals (1)){
//todo 如果是男生
}
如上代碼的弊端如下:
user一定是對(duì)象一定是被實(shí)例化后的嗎?如果user是null的話,直接使用會(huì)報(bào)空指針異常。 字符串直接==比對(duì)不是比對(duì)的Value。相信學(xué)習(xí)java時(shí)就會(huì)重點(diǎn)說(shuō)明,但是不巧,開發(fā)中我也見過(guò)有這種寫法。 字符串通過(guò)eq方法比對(duì)值一般是沒有問(wèn)題的,但是字符串類型的eq方法里傳入的是一個(gè)Object類型的值,因此,即使傳入一個(gè)數(shù)值類型也不會(huì)編譯錯(cuò)誤。如果誤寫成“1”.equals(1)將永遠(yuǎn)返回false。因此這種不容易發(fā)現(xiàn)的問(wèn)題,常常導(dǎo)致嚴(yán)重的bug。
public static void main (String[] args)
{
String man = "1";
Integer sex = 1;
System.out.println (man.equals (sex));
//輸出
//false
}
另外,項(xiàng)目中直接通過(guò)字符串匹配,代碼的可讀性也會(huì)變差。多人開發(fā)的時(shí)候又有誰(shuí)能夠保證你說(shuō)的狀態(tài)1(String)和我說(shuō)的狀態(tài)1(Integer)是同一個(gè)1呢。
1.2、數(shù)值匹配
上面列舉了字符串匹配,數(shù)值匹配同樣也有容易出問(wèn)題的寫法。
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);
}
因此,當(dāng)比對(duì)的數(shù)值在[-128,127]的范圍中,通過(guò)==對(duì)比會(huì)返回true,否則返回false,所以如果調(diào)用接口時(shí),返回的狀態(tài)碼是數(shù)值型的200的時(shí)候,判斷就需要注意一下。
另外,Integer也有eq方法,與String類型一樣,傳入Object類型,Integer.equals("1")也不會(huì)編譯報(bào)錯(cuò)。
二、代碼優(yōu)化
2.1、枚舉對(duì)應(yīng)數(shù)據(jù)庫(kù)字段
例如如上定義,通過(guò)表明+Enum定義java類名,類中通過(guò)枚舉對(duì)應(yīng)到數(shù)據(jù)庫(kù)的字段,這樣可以在多人開發(fā)時(shí)避免出現(xiàn)狀態(tài)碼定位不一致問(wèn)題,從而使得代碼有一個(gè)良好的可讀性。
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;
}
}
//按照如上寫法,同樣可以有 狀態(tài)碼:正常,禁用,刪除
//public enum Status
// 角色:管理員,普通用戶
//public enum role
}
2.2、數(shù)值轉(zhuǎn)換枚舉
在開發(fā)接口給前端開發(fā)時(shí),前端會(huì)傳入數(shù)值類型的狀態(tài),這時(shí)需要與對(duì)應(yīng)的枚舉類型進(jìn)行轉(zhuǎn)換。
代碼如下:
public static void main (String[] args)
{
//此處假如客戶端傳入狀態(tài)碼 1
Integer man =1;
UserEnum.Sex parse = UserEnum.Sex.parse (man);
System.out.println (parse);
}
2.3、枚舉使用switch
public static void main (String[] args)
{
//此處假如客戶端傳入狀態(tài)碼 1
Integer man =1;
UserEnum.Sex parse = UserEnum.Sex.parse (man);
switch (parse){
case Man:
//todo
break;
case WOMAN:
//todo
break;
}
}
2.4、枚舉狀態(tài)機(jī)
雖然常有項(xiàng)目組通過(guò)常量來(lái)使得代碼更加規(guī)范,但是通過(guò)枚舉可以在多狀態(tài)轉(zhuǎn)換的場(chǎng)景下使得代碼更加友好的呈現(xiàn)。
在一個(gè)請(qǐng)假單的審批過(guò)程中肯定有這幾種狀態(tài)<發(fā)起審批,組長(zhǎng)審批,經(jīng)理審批,人事備案>。狀態(tài)機(jī)代碼示例:
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
//審批狀態(tài)碼
public enum ApprovalStatusEnum
{
START(1,"開始審批"){
@Override
ApprovalStatusEnum getNextStatus ()
{
return first_leader;
}
},
first_leader(2,"第一個(gè)領(lǐng)導(dǎo)審批"){
@Override
ApprovalStatusEnum getNextStatus ()
{
return second_leader;
}
},
second_leader(3,"第二個(gè)領(lǐng)導(dǎo)審批"){
@Override
ApprovalStatusEnum getNextStatus ()
{
return backups;
}
},
backups(4,"備案"){
@Override
ApprovalStatusEnum getNextStatus ()
{
return null;
}
};
private Integer code;
private String msg;
abstract ApprovalStatusEnum getNextStatus();
}
在枚舉類中定義抽象方法,并且在每個(gè)狀態(tài)中進(jìn)行具體的實(shí)現(xiàn)。如此在有大量的狀態(tài)轉(zhuǎn)移的場(chǎng)景中(固定的審批場(chǎng)景,支付場(chǎng)景),當(dāng)前狀態(tài)調(diào)用nextStatus()方法獲取下一個(gè)狀態(tài)。這種寫法可以使得代碼更加簡(jiǎn)潔干凈,更加便于維護(hù)。
我已經(jīng)更新了我的《10萬(wàn)字Springboot經(jīng)典學(xué)習(xí)筆記》中,點(diǎn)擊下面小卡片,進(jìn)入【武哥聊編程】,回復(fù):筆記,即可免費(fèi)獲取。
點(diǎn)贊是最大的支持

