詳解Java枚舉與接口常量和類常量的區(qū)別
一個(gè)簡單的需求
在我們實(shí)際開發(fā)java項(xiàng)目過程中,突然有一天"領(lǐng)導(dǎo)老王"給了個(gè)任務(wù), 公司系統(tǒng)需要支持商品管理的需求
比如水果有:蘋果,香蕉,葡萄等等,電子產(chǎn)品有:電腦,手機(jī),攝像機(jī)等等
我們一般新建商品類Goods
:
public class Goods { /** * 商品名稱 */ private String name; /** * 商品類型 */ private Integer type; public Goods(String name, Integer type) { this.name = name; this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getType() { return type; } public void setType(Integer type) { this.type = type; } }
然后我們就直接可以使用它:
public class GoodsTest { public static void main(String[] args) throws InterruptedException { Goods goods = new Goods("水果",1);//1代表蘋果,2:香蕉,3:葡萄 System.out.println(goods.getName()); } }
但是有個(gè)問題,業(yè)務(wù)代碼不清晰,有時(shí)候開發(fā)人員并不知道1、2、3代表什么意思,而且在業(yè)務(wù)代碼層里面直接寫數(shù)字或者字符串也是非常危險(xiǎn)的時(shí),我們需要一種方案,既能將相關(guān)的狀態(tài),類型放在一起,又可以限制類的輸入值,提升項(xiàng)目的安全性
接口常量
我們可以使用接口常量來解決上面的問題
public interface StatusContentFace { public static final String fruit = "fruit"; public static final Integer apple = 1; public static final Integer banana = 2; public static final Integer grape = 3; //========================== public static final String eleProduct = "eleProduct"; public static final Integer computer = 101; public static final Integer phone = 102; public static final Integer camera = 103; }
我們?cè)賮砜聪聹y(cè)試類:
public class GoodsTest1 { public static void main(String[] args) throws InterruptedException { Goods goods = new Goods(StatusContentFace.fruit,StatusContentFace.apple); Goods goods_2 = new Goods(StatusContentFace.eleProduct,StatusContentFace.computer); System.out.println(goods.getName()); System.out.println(goods_2.getName()); } }
這樣能夠讓相關(guān)的常量都在同一個(gè)接口文件中,接口常量,寫起來比較簡潔,但是為了讓其他人知道每個(gè)常量的含義,最好寫上注釋。
但它同時(shí)有個(gè)問題,由于java中接口是支持多繼承的
- 我們可以將內(nèi)容深入到其實(shí)現(xiàn)類代碼中,這樣對(duì)于一個(gè)常量類接口來說顯然是不合理。
- 我們還可以在其子接口里繼續(xù)添加常量,這樣在祖先接口中就無法控制所有常量,這樣無疑是非常危險(xiǎn)的。
一般不建議用的,但接口常量也不是一無是處的,可以通過內(nèi)部接口來實(shí)現(xiàn)分組效果
public class GoodsTest2 { public static void main(String[] args) throws InterruptedException { Goods goods = new Goods(Fruit.type,Fruit.banana); Goods goods_2 = new Goods(EleProduct.type,EleProduct.phone); System.out.println(goods.getName()); System.out.println(goods_2.getName()); } //常量分組 public interface Fruit { String type = "fruit"; Integer apple = 1; Integer banana = 2; Integer grape = 3; } public interface EleProduct { String type = "eleProduct"; Integer computer = 101; Integer phone = 102; Integer camera = 103; } }
這樣我們可以把相關(guān)的常量都?xì)w為一類,更加簡潔明了
類常量
我們一般常用的是類常量方式:
public final class StatusConstant { private StatusConstant() {} //防止該類實(shí)例化 public static final String fruit = "fruit"; public static final Integer apple = 1; public static final Integer banana = 2; public static final Integer grape = 3; //========================== public static final String eleProduct = "eleProduct"; public static final Integer computer = 101; public static final Integer phone = 102; public static final Integer camera = 103; }
注意:一般用final關(guān)鍵字修飾 class 防止其被繼承,并將其構(gòu)造函數(shù) private 化,防止被實(shí)例化
測(cè)試類:
public class GoodsTest3 { public static void main(String[] args) throws InterruptedException { Goods goods = new Goods(StatusConstant.fruit, StatusConstant.banana); Goods goods_2 = new Goods(StatusConstant.eleProduct, StatusConstant.phone); System.out.println(goods.getName()); System.out.println(goods_2.getName()); } }
我們可以發(fā)現(xiàn)類常量的方式,的確很方便,也沒有接口常量多繼承的煩惱。但是她所能承接的信息,維度不夠,只能一個(gè)字段的去承接信息,然而當(dāng)項(xiàng)目復(fù)雜的話,我們希望往往其能承接更多維度的信息,類似于對(duì)象一樣,擁有更多的屬性
{ "name": ..., "type": ..., ... }
這時(shí)候,我們本文的主角,枚舉就閃亮登場(chǎng)了!
枚舉
什么是枚舉
枚舉是一種特殊的類,所有的枚舉類都是Enum類的子類,就類似Object類一樣,由于java類是單繼承的,所以不能在繼承其他類或者枚舉了。
枚舉變量不能使用其他的數(shù)據(jù),只能使用枚舉中常量賦值。能提高程序的安全性。
格式:
public enum 枚舉名{
//枚舉的取值范圍
}
枚舉常量
我們先定義一個(gè)枚舉類,來定義常量:
public enum ContentEnums { Apple(1,"蘋果"), Banana(2,"香蕉"), Grape(3,"葡萄"), Computer(101,"電腦"), Phone(102,"手機(jī)"), Camera(103,"攝像機(jī)"), Fruit(10010,"fruit"), EleProduct(10020,"eleProduct"); private Integer code; private String desc; ContentEnums(Integer code, String desc) { this.code = code; this.desc = desc; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } }
測(cè)試類:
public class GoodsTest4 { public static void main(String[] args) throws InterruptedException { Goods goods = new Goods(ContentEnums.Fruit.getDesc(), ContentEnums.Apple.getCode()); Goods goods_2 = new Goods(ContentEnums.EleProduct.getDesc(), ContentEnums.Phone.getCode()); System.out.println(goods.getName()); System.out.println(goods_2.getName()); } }
看到這大家可能就有疑問了,枚舉和常量類相比,有什么優(yōu)點(diǎn)嗎?
1.枚舉其實(shí)是一種特殊的類,可以承接對(duì)象的多維信息,但是常量類往往只能承接字段,信息比較單一
2.枚舉可以搭配switch語句使用,來代替if/else
ContentEnums content = ContentEnums.Apple; switch (content) { case Apple: System.out.println("蘋果"); break; case Banana: System.out.println("香蕉"); break; case Grape: System.out.println("葡萄"); break; default: System.out.println("未找到匹配類型"); }
3.enum 有一個(gè)非常有趣的特性,它可以為enum實(shí)例編寫方法
public enum MethodEnums { VERSION { @Override String getInfo() { return System.getProperty("java.version"); } }, DATE_TIME { @Override String getInfo() { return DateFormat.getDateInstance() .format(new Date()); } }; abstract String getInfo(); public static void main(String[] args) { for(MethodEnums csm : values()) { System.out.println(csm.getInfo()); } } }
結(jié)果:
1.8.0_271
2022-9-21
除了抽象方法,普通方法也是可以的,這里就不展示了
4.網(wǎng)上還有其他一些優(yōu)點(diǎn),感覺沒啥特別值得說的
限制輸入的類型
我們可以通過枚舉來將相關(guān)的狀態(tài),類型放在一起,文章一開頭,但我們?cè)趺床拍芟拗祁惖妮斎胫的??其?shí)很簡單,別被繞進(jìn)去,我們只需將輸入類型 改為指定的枚舉即可
我們改造一下Goods類:
public class Goods { /** * 商品名稱 */ private String name; /** * 商品類型 */ private Integer type; // public Goods(String name, Integer type) { // this.name = name; // this.type = type; // } public Goods() {//防止外部實(shí)例化 } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getType() { return type; } public void setType(Integer type) { this.type = type; } public static Goods addGoods(ContentEnums enums){ Goods goods = new Goods(); goods.setName(enums.getDesc()); goods.setType(enums.getCode()); return goods; } }
測(cè)試類:
public class GoodsTest5 { public static void main(String[] args) throws InterruptedException { Goods goods = Goods.addGoods(ContentEnums.Apple); Goods goods_2 = Goods.addGoods(ContentEnums.Computer); System.out.println(goods.getName()); System.out.println(goods_2.getName()); } }
這樣,我們就可以限制創(chuàng)建對(duì)象時(shí)的輸入值類型了
枚舉可以使用==來比較嗎
可以使用==
來比較 enum 實(shí)例,編譯器會(huì)自動(dòng)為你提供equals()
和 hashCode()
方法。Enum
類實(shí)現(xiàn)了 Comparable
接口,所以它具有 compareTo()
方法。同時(shí),它還實(shí)現(xiàn)了 Serializable
接口。
枚舉實(shí)現(xiàn)單例
枚舉類型是天生線程安全的,并且只會(huì)裝載一次,我們可以利用了枚舉的這個(gè)特性來實(shí)現(xiàn)單例
public enum SingleInstance { INSTANCE; public void funDo() { System.out.println("doSomething"); } }
使用方式:SingleInstance.INSTANCE.funDo()
這種方法充分 利用枚舉的特性,讓JVM來幫我們保證線程安全和單一實(shí)例的問題。寫法也極其簡潔。
以上就是詳解Java枚舉與接口常量和類常量的區(qū)別的詳細(xì)內(nèi)容,更多關(guān)于Java枚舉 接口常量 類常量的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
MyBatis使用標(biāo)簽動(dòng)態(tài)操作數(shù)據(jù)庫詳解
這篇文章主要介紹了MyBatis中使用標(biāo)簽動(dòng)態(tài)操作數(shù)據(jù)庫的方法,動(dòng)態(tài)SQL是指在運(yùn)行PL/SQL塊時(shí)動(dòng)態(tài)輸入SQL語句,是Mybatis的強(qiáng)大特性之?,能夠完成不同條件下不同的sql拼接,需要的朋友可以參考下2024-05-05Java List的remove()方法陷阱以及性能優(yōu)化
Java List在進(jìn)行remove()方法是通常容易踩坑,本文就詳細(xì)的介紹一下陷阱以及性能優(yōu)化,感興趣的可以了解一下2021-10-10使用Feign實(shí)現(xiàn)微服務(wù)間文件下載
這篇文章主要為大家詳細(xì)介紹了使用Feign實(shí)現(xiàn)微服務(wù)間文件下載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04聊聊java中一些減少if else 的編碼習(xí)慣的方法
這篇文章主要介紹了聊聊java中一些減少if else 的編碼習(xí)慣的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Sleuth(Micrometer)+ZipKin分布式鏈路問題小結(jié)
在微服務(wù)架構(gòu)中,分布式鏈路追蹤技術(shù)成為了解決系統(tǒng)復(fù)雜調(diào)用問題的關(guān)鍵,本文介紹了其他鏈路追蹤方案,如Cat、Pinpoint和Skywalking,展示了分布式鏈路追蹤技術(shù)的多樣化,感興趣的朋友一起看看吧2024-10-10