《Java編程思想》中有這么一句話:“有時(shí)恰恰因?yàn)樗?,你才能夠‘?yōu)雅而干凈’地解決問題”——這句話說的是誰呢?就是本篇的主角——枚舉(Enum)——大家鼓掌了。
在之前很長(zhǎng)時(shí)間一段時(shí)間里,我都不怎么用枚舉,因?yàn)榭偢杏X它沒什么用處——這其實(shí)就是“自我認(rèn)知”的短見。當(dāng)一個(gè)人一直蹲在自己的深井里而不敢跳出來的話,那他真的只能看到井口那么大點(diǎn)的天空。
隨著時(shí)間的推移,我做的項(xiàng)目越來越多,和枚舉見面的機(jī)會(huì)也越來越多,于是我就漸漸地對(duì)它越來越有興趣,研究得多了,才發(fā)現(xiàn)原來枚舉如此的優(yōu)秀。
一個(gè)精簡(jiǎn)的枚舉非常的干凈優(yōu)雅,見下例。
public enum Chenmo {
WANGER, WANGSAN, WANGSI
}
我們?yōu)槌聊杜e創(chuàng)建了三個(gè)值,分別是王二、王三、王四。這段代碼實(shí)際上調(diào)用了3次Enum(String name, int ordinal)
(ordinal單詞的意思為順序),也就是:
new Enum<Chenmo>("WANGER", 0);
new Enum<Chenmo>("WANGSAN", 1);
new Enum<Chenmo>("WANGSI", 2);
我們來遍歷輸出一下枚舉:
for (Chenmo e : Chenmo.values()) {
System.out.println(e);
}
//輸出
//WANGER
//WANGSAN
//WANGSI
使用枚舉作為switch語句判斷條件能讓我們的代碼可讀性更強(qiáng),示例如下。
Chenmo key = Chenmo.WANGER;
switch (key) {
case WANGSI:
System.out.println("今天我送出一個(gè)CSDN大鼠標(biāo)墊");
break;
case WANGSAN:
System.out.println("今天我被坑一個(gè)CSDN學(xué)院年卡");
break;
default:
System.out.println("今天我一邊高興,一邊失落");
break;
}
在通過case關(guān)鍵字判斷的時(shí)候,可以直接使用枚舉值,非常簡(jiǎn)潔。另外,在編譯期間限定類型,可以有效的避免越界的情況——字符串常量類型在作為switch判斷條件的時(shí)候很容易因?yàn)檎`寫而發(fā)生越界問題。
《Effective Java》一書中對(duì)使用枚舉實(shí)現(xiàn)單例的方式推崇備至:
使用枚舉實(shí)現(xiàn)單例的方法雖然還沒有廣泛采用,但是單元素的枚舉類型已經(jīng)成為實(shí)現(xiàn)Singleton的最佳方法。
我覺得“雖然還沒有廣泛采用”幾個(gè)字可以去掉了,時(shí)至今日,大家應(yīng)該都知道:使用枚舉實(shí)現(xiàn)單例是一種非常好的方式。
先來看“雙重校驗(yàn)鎖”實(shí)現(xiàn)的單例:
public class SingleTon2 {
// 私有化構(gòu)造方法
private SingleTon2() {
};
private static volatile SingleTon2 singleTon = null;
public static SingleTon2 getInstance() {
// 第一次校驗(yàn)
if (singleTon == null) {
synchronized (SingleTon2.class) {
// 第二次校驗(yàn)
if (singleTon == null) {
singleTon = new SingleTon2();
}
}
}
return singleTon;
}
}
再來看枚舉實(shí)現(xiàn)的單例:
public enum SingleTon {
INSTANCE;
public void method() {
System.out.println("我很快樂!");
}
}
不比不知道,一比嚇一跳啊!枚舉方式的單例簡(jiǎn)單到爆——為了不至于看起來太過精簡(jiǎn),我還加了一個(gè)輸出“我很快樂”的方法。
枚舉實(shí)現(xiàn)的單例可輕松地解決兩個(gè)問題:
①、線程安全問題。因?yàn)镴ava虛擬機(jī)在加載枚舉類的時(shí)候,會(huì)使用ClassLoader的loadClass方法,這個(gè)方法使用了同步代碼塊來保證線程安全。
②、避免反序列化破壞單例。因?yàn)槊杜e的反序列化并不通過反射實(shí)現(xiàn)。
我們可以配合Mybatis將數(shù)據(jù)庫(kù)字段轉(zhuǎn)換為枚舉類型?,F(xiàn)在假設(shè)有一個(gè)數(shù)據(jù)庫(kù)字段check_type的類型如下:
`check_type` int(1) DEFAULT NULL COMMENT '檢查類型(1:未通過、2:通過)',
它對(duì)應(yīng)的枚舉類型為CheckType,代碼如下:
public enum CheckType {
NO_PASS(0, "未通過"), PASS(1, "通過");
private int key;
private String text;
private CheckType(int key, String text) {
this.key = key;
this.text = text;
}
public int getKey() {
return key;
}
public String getText() {
return text;
}
private static HashMap<Integer,CheckType> map = new HashMap<Integer,CheckType>();
static {
for(CheckType d : CheckType.values()){
map.put(d.key, d);
}
}
public static CheckType parse(Integer index) {
if(map.containsKey(index)){
return map.get(index);
}
return null;
}
}
CheckType枚舉類比我們剛開始見到的那個(gè)Chenmo枚舉類要復(fù)雜一些。
第一,CheckType新添加了構(gòu)造方法,還有兩個(gè)字段,key為int型,text為String型。
第二,CheckType中有一個(gè)public static CheckType parse(Integer index)
方法,可將一個(gè)Integer通過key的匹配轉(zhuǎn)化為枚舉類型。
那么現(xiàn)在,我們可以在Mybatis的配置文件中使用typeHandler
將數(shù)據(jù)庫(kù)字段轉(zhuǎn)化為枚舉類型。
<resultMap id="CheckLog" type="com.entity.CheckLog">
<id property="id" column="id"/>
<result property="checkType" column="check_type" typeHandler="com.CheckTypeHandler"></result>
</resultMap>
其中checkType字段對(duì)應(yīng)的類如下:
public class CheckLog implements Serializable {
private String id;
private CheckType checkType;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public CheckType getCheckType() {
return checkType;
}
public void setCheckType(CheckType checkType) {
this.checkType = checkType;
}
}
CheckTypeHandler轉(zhuǎn)換器的類源碼如下:
public class CheckTypeHandler extends BaseTypeHandler<CheckType> {
@Override
public CheckType getNullableResult(ResultSet rs, String index) throws SQLException {
return CheckType.parse(rs.getInt(index));
}
@Override
public CheckType getNullableResult(ResultSet rs, int index) throws SQLException {
return CheckType.parse(rs.getInt(index));
}
@Override
public CheckType getNullableResult(CallableStatement cs, int index) throws SQLException {
return CheckType.parse(cs.getInt(index));
}
@Override
public void setNonNullParameter(PreparedStatement ps, int index, CheckType val, JdbcType arg3) throws SQLException {
ps.setInt(index, val.getKey());
}
}
CheckTypeHandler 的核心功能就是調(diào)用CheckType枚舉類的parse()
方法對(duì)數(shù)據(jù)庫(kù)字段進(jìn)行轉(zhuǎn)換。
說完枚舉最常用的4個(gè)知識(shí)點(diǎn)后,我們來討論一下“枚舉會(huì)比靜態(tài)常量更消耗內(nèi)存嗎?”這個(gè)話題——知乎上有人問這樣的問題,還有很多人參與回答。
按我的理解,問這個(gè)問題的人就好像是在問“0.000,001”比“0.000,000,99”大嗎?你說是嗎?
上一篇:如果有人再問你 Java 的反射,把這篇文章扔給他
下一篇:Java注解(Annotation):請(qǐng)不要小看我!
微信搜索「*沉默王×××免費(fèi)視頻**」獲取 500G 高質(zhì)量教學(xué)視頻(已分門別類)。
創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國(guó)云服務(wù)器,動(dòng)態(tài)BGP最優(yōu)骨干路由自動(dòng)選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨(dú)有T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動(dòng)現(xiàn)已開啟,新人活動(dòng)云服務(wù)器買多久送多久。
當(dāng)前文章:Java枚舉:小小enum,優(yōu)雅而干凈-創(chuàng)新互聯(lián)
鏈接分享:http://m.rwnh.cn/article46/dggshg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供標(biāo)簽優(yōu)化、外貿(mào)網(wǎng)站建設(shè)、外貿(mào)建站、靜態(tài)網(wǎng)站、微信公眾號(hào)、網(wǎng)站維護(hù)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容