文章簡單,相信在很多網站都能搜尋到java enum枚舉的使用方式;可能有些東西我當時在剛開始用的時候沒找到,是以我寫了這篇文章,例如:
大多數地方寫的枚舉都是給一個枚舉然後例子就開始switch,可是我想說,我代碼裡頭來源的資料不太可能就是枚舉,通常是字元串或數字,比如一個sql我解析後首先判定sql類型,通過截取sql的token,截取出來可能是select、delete、update、insert、alter等等,但是都是字元串,此時我想用枚舉就不行了,我要将字元串轉換成枚舉怎麼轉呢,類似的情況還有從資料庫取出資料根據一些類型做判定,從頁面傳入資料,根據不同的類型做不同的操作,但是都是字元串,不是枚舉,悲劇的是我很少看到有人寫到這個東西;是以我把它寫下來,希望有人能用到。
首先為什麼要用枚舉?我們在什麼時候用枚舉比較好,用枚舉有啥優勢?
我認為哈,當你在一些一個範疇類,并可列舉,不變化的類型,用以指導程式向不同的地方路由,用枚舉是較好的選擇;
聽起來有點繞,不過有個例子也許可以明白,例如:
我們可以列舉下日常工作日所做的事情:
上班、開會、吃飯、睡覺等
我們可以列舉醫院五官科需要檢查人的部位:
眼睛、鼻子、耳朵、嘴巴等
這些都是可以被列舉的,且每種事情我們要用不同的方式去做;
當然你可以說:
1、可以用動态方法分派,通過配置檔案或annotation;
2、可以使用常量來達到類似的效果;
3、直接通過字元串的equals來表達,用if else來表達
如果用配置加方法分派來做,是靈活,便于修改;但是如果在很多不經常修改的參數上,我們用這中方式往往增加配置的負擔,并且當你需要看系統邏輯的時候,需要需要一遍看配置一遍看代碼;不過,如果參數是可動态變換的資訊,用配置是正确的選擇;
而常量的使用,通常在switch case的時候都是數字,字元串在java中是不能做switch case的,使用常量的目的比case 1、case 2 ...這種增加了可讀性;但是字元串資料也麻煩,除非再映射一次,那沒那個必要,其實枚舉也差不多是幫你映射了一次,隻是它将代碼封裝了而已吧了,既然他弄好了,而且文法上支援,幹嘛不用呢!其次,常量雖然增加了可讀性,不過他沒有範疇和管理類型的概念,即一個枚舉的定義會定義個範疇,可以很好的将這個範圍所需要的東西列舉出來,而常量通常是些自己定義的一些池,放在一些公共類中或随機定義,都是比較零散的,并且枚舉在switch的時候就明确定義好了就在鎖列舉的範圍内case,既可以控制好系統,增加可讀性,并且可以随時檢視這個範疇的枚舉資訊到底有那些,達到類似看配置檔案的作用;不過還是回到那句話,如果參數是可變的,那麼就不适合做枚舉,枚舉是一定是可列舉的,或者說目前系統考慮範圍是可以被枚舉的,例如上面的醫院五官科,可能還有很多沒有列舉到,但是目前醫院隻處理幾個部位,不處理其他的,就是這個道理;什麼是可變的呢,例如url參數來分派到對應方法,不可能大家加一段邏輯就去加一個枚舉,加一個case,此時用【配置+動态方法分派】更好,當然配置可以用檔案或annotation而已。
還有最土的就是,通過字元串equals,用if else來實作,呵呵,這個并沒有什麼不好,隻是這個寫比較零散,其次,字元串比對的equals每次比對都需要對比每個字元,如果你的代碼中大量循環,性能并不是很好,其餘的看看上面的描述就更加清楚了;
其次,枚舉提供一種類型管理的元件,讓面向對象的體系更加完善,使得一些類型的管理既可配置化,并可以管理,在使用枚舉的地方都可以沿着枚舉的定義找到那些有處理過,那些沒處理過,而上述幾種很難做到;例如,資料庫的操作類型定義了10種,那麼再判定的過程中就可以講枚舉像配置檔案一樣看待,而又非常簡單的來管理。
最後,枚舉絕對是單例的,對比的性能和數字性能相當,既可以得到可讀性,也可以得到性能。
我們先定義個簡單枚舉(這裡隻是個例子,就簡單定義3個變量了):
此時解析sql後,擷取出來一個token,我們要擷取這個token的枚舉怎麼擷取呢?
這樣擷取:
如果沒擷取到,java會抛出一個異常哦:illegalargumentexception no enum const class sqltypeenum.xxx
我做大寫處理的原因是因為枚舉也是大寫的(當然如果你的枚舉是小寫的,那你就小寫,不過混寫比較麻煩哈),其實valueof就是調用了枚舉的底層映射:
調用的時候會調用這個方法:
是以内部也是一個hashmap,呵呵!
拿到這個資訊後,就可以做想要的操作了:
ok,有些時候可能我們不想直接用insert、update這樣的字元串在互動中使用,因為很多時候命名規範的要求;
例如定義一些使用者操作類型:
1、儲存使用者資訊
2、通過id擷取使用者基本資訊
3、擷取使用者清單
4、通過id删除使用者資訊
等等
我們可能定義枚舉會定義為:
但是系統的方法和一些關鍵字的配置,通常會寫成:
saveuser、getuserbyid、getuserbyid、deleteuserbyid
當然各自有各自的規則,不過中間這層映射,你不想做,就一方面妥協,要麼枚舉名稱全部換掉,貌似挺奇怪的,要麼方法名稱全部換掉,更加奇怪,要麼自己做映射,可以,稍微麻煩點,其實也不麻煩?
我們首先寫個将枚舉下劃線風格的資料轉換為駝峰的方法,放在一個stringutils裡面:
重載一個方法:
然後定義枚舉:
ok,這樣傳遞一個event參數讓如果是:saveuser,此時就用:
其實就是自己做了一個hashmap,我這加了一個fromstring,因為枚舉有一些限制,有些方法不讓你覆寫,比如valueof方法就是這樣。
其實沒啥好講的了,非要說,再說說枚舉加一些自定義變量吧,其實枚舉除了是單例的外,其餘的和普通類也相似,它也可以有構造方法,隻是預設情況下不是而已,也可以提供自定義的變量,然後擷取set、get方法,但是如果有set的話,線程不是安全的哦,要注意這點;是以一般是構造方法就寫好了:
調用下:
不推薦也調用下:
在另一個線程:
發現結果被改了,呵呵!