淺談Java中是否直接可以使用enum進行傳輸
背景
我們在進行傳輸?shù)臅r候 會有一些狀態(tài)值,如Status為1代表刪除,為0代表失敗或者怎么樣的。只傳輸一個)0或者1過去給第三方(此處不包括給前端),如果沒有契約第三方會不認識你這個是什么意思,那我們在平時寫業(yè)務邏輯的時候使用枚舉很輕易就知道了什么狀態(tài)什么值。所以我們在構建DTO對象的時候里面放一個枚舉來表示。
首先在阿里的規(guī)范里是這樣說的:
【強制】二方庫里可以定義枚舉類型,參數(shù)可以使用枚舉類型,但是接口返回值不允許使用枚舉類型或者包含枚舉類型的 POJO 對象。
那到底為啥不能用呢?
枚舉
首先我們得先思考一下枚舉是否可以進行序列化,我們在把對象進行傳輸?shù)臅r候需要將這個對象序列化為字節(jié)序列進行傳輸(在linux中一切皆文件,JVM虛擬機將對象變?yōu)樽止?jié)給到內核通過傳輸協(xié)議進行打包傳)枚舉在進行編譯后會生成一個相關的類,這個類,這個類繼承了JavaAPI中的java.lang.Enum類。那么我們看看這個類,毫無疑問可以序列化。繼承了Serializable接口。那么就肯定就是可以序列化了。

Enum實戰(zhàn)序列化
1. 創(chuàng)建一個枚舉類
package SerializableEnum;
/**
* @Author:yuanxindong
* @Date:2020/5/101:33
*/
public enum PersonEnum {
/**
* 小圓
*/
YUANXINDONG("yuanxindong",1);
;
private String age;
private int i;
PersonEnum(String yuanxindong, int i) {
this.age = yuanxindong;
this.i = i;
}}
2.將枚舉類放入Person對象,通過本地序列化存入target文件夾中,再進行反序列化,讀取查看枚舉的值
package SerializableEnum;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* @Author:yuanxindong
* @Date:2020/5/101:31
*/
public class Person implements Serializable {
private String name;
PersonEnum a;
public void setName(String name) {
this.name = name;
}
public void setA(PersonEnum a) {
this.a = a;
}
public String getName() {
return name;
}
public PersonEnum getA() {
return a;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", a=" + a +
'}';
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"));
Person p = new Person();
p.setA(PersonEnum.YUANXINDONG);
p.setName("小圓");
oos.writeObject(p);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\workCode\\票稅助手\\aresV3\\springCodestudy\\object.txt"));
Person brady = (Person) ois.readObject();
brady.getA();
System.out.println(brady);
}
}
執(zhí)行結果:

但是在控制臺輸出的對象是枚舉的命名,沒有枚舉中的值,這時為什么呢?

==
我用的是aliFastJson轉還為JsonObject的我們看看他里面的實現(xiàn)。只是拿了對應枚舉的name(感覺是個坑?。?,這也阿里規(guī)范中不能使用枚舉放在DTO的原因之一吧==

上面的內容整明了枚舉是可以進行序列化的,是可以被傳輸?shù)?,他的實現(xiàn)也是通過類來實現(xiàn)的,除了fastJSON那一步,使用都沒有問題的。其他角度考慮
借鑒知乎
使用枚舉的確會帶來擴展兼容性的問題,這點很多答主都說的很好了,我就說一下為什么參數(shù)上可以使用枚舉的原因吧。咱們先假定對枚舉的擴展只是新增值,而不是減少值。比如說性別中本來是男和女,現(xiàn)在要增加一個transgender, 但我們極少極少會有需求說,把性別中的已有男或者女去掉。(我覺得這個假設是參數(shù)可以使用枚舉型的前提)在這個假定下如果我們在接口中使用枚舉型,如孤盡兄在java開發(fā)手冊中所述,分為參數(shù)和返回值兩種情況。不管是微服務之間的互相調用,還是手機客戶端到服務器的調用,在不停機的情況下,服務器端和客戶端是很難一起更新的,往往我們是服務器端先來支持新feature,然后再來逐步更新客戶端。我想孤盡兄說參數(shù)可以使用枚舉型,也是基于這種更新升級方式。因為服務器端如果突然開始返回transgender這個新性別,客戶端吃不進去(反序列化不了),客戶端就炸了。但如果服務器端只是在參數(shù)上開始接受新性別,那就不怕老客戶端,反正老客戶端還在那里繼續(xù)發(fā)送男和女這兩種性別,服務器端都認識,就不會出錯。兩邊可以一直相安無事,慢慢等所有客戶端都升級。但是呢,如果我們用string來代替枚舉,服務器端貿(mào)然返回一個新的值,客戶端不知道怎么處理,也可能會產(chǎn)生其他問題,比如說錢算錯了之類業(yè)務層面的問題。所以客戶端代碼可能要先更新一點,讓其能處理這個新的值。我覺得阿里把這個標準放在手冊里,也是多年的經(jīng)驗教訓,兩害相權取其輕吧。因為很多應用是沒法強制客戶端一起更新的。尤其是手機移動客戶端,ios可能還要審核,很難做到客戶端和服務器端同步更新。如果是微服務,也很難在不停機的情況下,把通過枚舉耦合兩個微服務一起更新。
看完大佬的說法個人感覺:
是的你在一個項目中維護是沒有什么問題。但是多個項目使用同一個枚舉怎么搞。要么這個枚舉一處動即全動。所有的項目使用這一個枚舉。比如說全公司有一個通用的發(fā)票類型枚舉,有幾個狀態(tài)值代表一鐘發(fā)票類型,于是這個枚舉維護到公共配置上,通過動態(tài)加載技術,在每次發(fā)布或者有修改的時候進行動態(tài)加載。感覺同完美。小白的YY。落地難嗎??試一試。后面更新。
到此這篇關于淺談Java中是否直接可以使用enum進行傳輸?shù)奈恼戮徒榻B到這了,更多相關Java enum 傳輸內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
在CentOS系統(tǒng)中檢測Java安裝及運行jar應用的方法
這篇文章主要介紹了在CentOS系統(tǒng)中檢測Java安裝及運行jar應用的方法,同樣適用于Fedora等其他RedHat系的Linux系統(tǒng),需要的朋友可以參考下2015-06-06
java如何利用poi解析doc和docx中的數(shù)據(jù)
這篇文章主要給大家介紹了關于java如何利用poi解析doc和docx中數(shù)據(jù)的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-04-04

