測者的測試技術(shù)手冊:Junit單元測試遇見的一個(gè)枚舉類型的坑(枚舉類型詳解)

Enum的簡介

枚舉類型很早就在計(jì)算機(jī)語言中存在了,主要被用來將一組相似的值包含進(jìn)一種類型中涌攻,這種類型的名稱被定義成獨(dú)一無二的類型描述符嫉入,這就是枚舉類型瞎嬉。

在java語言中,枚舉類型是一個(gè)完整功能的類救巷,允許開發(fā)者給枚舉類型添加方法和屬性,同時(shí)也可以提供接口。同時(shí)Java也為Enum提供了高質(zhì)量的實(shí)現(xiàn)挽懦,比如comparable和Serializable接口.

* 其中:Comparable 是排序接口,如果一個(gè)Java類有這個(gè)接口木人,那么只能說明這個(gè)類支持排序信柿。即然實(shí)現(xiàn)Comparable接口的類支持排序,假設(shè)現(xiàn)在存在“實(shí)現(xiàn)Comparable接口的類的對象的List列表(或數(shù)組)醒第,則該List列表(或數(shù)組)可以通過 Collections.sort(或 Arrays.sort)進(jìn)行排序渔嚷。“實(shí)現(xiàn)Comparable接口的類的對象”可以用作“有序映射(如TreeMap)”中的鍵或“有序集合(TreeSet)”中的元素稠曼,而不需要指定比較器形病。

Serializable接口的對象轉(zhuǎn)換成一個(gè)字符序列,并能夠在以后將這個(gè)字節(jié)序列完全恢復(fù)為原來的對象霞幅。而且這個(gè)過程是可以通過網(wǎng)絡(luò)完成的漠吻,也就是說序列化機(jī)制能夠自動(dòng)彌補(bǔ)不同操作系統(tǒng)之間差異。*

Enum的定制

通過類的定義蝗岖,可以給Enum一些復(fù)雜的功能侥猩,例如下面代碼給Enum增加屬性:

public enum DrinkEnum{

// 酒

Wine("a cup of wine ");

//橙汁

Oragen_Juice("a cup of oragen juice")

//Enum對象的drink_class屬性

private String drink_class;

//枚舉對象構(gòu)造函數(shù)

private DrinkEnum(String drink){

? ?this.drink_class=drink;

}

//枚舉對象的drink_class屬性

public String getDrink(){

? ?return this.drink_class;

}

Enum的一些坑

1 Enum 不支持public和protected修飾符的構(gòu)造方法,因此構(gòu)造函數(shù)一定要是private或者friendly的抵赢,這也就約束了枚舉對象是無法在程序中通過直接調(diào)用構(gòu)造函數(shù)進(jìn)行初始化的欺劳。

2 Enum的值是通過運(yùn)行期構(gòu)造出來的對象表示的,因此在集群環(huán)境下铅鲤,每個(gè)jvm構(gòu)造出同義對象划提,但是在做布爾運(yùn)算的時(shí)候有可能有問題,因此要格外注意邢享。在對Enum進(jìn)行比較的時(shí)候鹏往,使用值比對。

Enum的原理

在使用enum創(chuàng)建枚舉類型后骇塘,編譯器會為其生成一個(gè)對應(yīng)的枚舉類伊履,這個(gè)類繼承與java.lang.Enum。舉例如下:

enum Day {

? ?MONDAY, TUESDAY, WEDNESDAY,

? ?THURSDAY, FRIDAY, SATURDAY, SUNDAY

}

編譯后會變成Day.class款违,那么測者反編譯后看到如下:

final class Day extends Enum

{

? ?//編譯器為我們添加的靜態(tài)的values()方法

? ?public static Day[] values()

? ?{

? ? ? ?return (Day[])$VALUES.clone();

? ?}

? ?//編譯器為我們添加的靜態(tài)的valueOf()方法唐瀑,注意間接調(diào)用了Enum也類的valueOf方法

? ?public static Day valueOf(String s)

? ?{

? ? ? ?return (Day)Enum.valueOf(com/zejian/enumdemo/Day, s);

? ?}

? ?//私有構(gòu)造函數(shù)

? ?private Day(String s, int i)

? ?{

? ? ? ?super(s, i);

? ?}

? ? //前面定義的7種枚舉實(shí)例

? ?public static final Day MONDAY;

? ?public static final Day TUESDAY;

? ?public static final Day WEDNESDAY;

? ?public static final Day THURSDAY;

? ?public static final Day FRIDAY;

? ?public static final Day SATURDAY;

? ?public static final Day SUNDAY;

? ?private static final Day $VALUES[];

? ?static

? ?{ ? ?

? ? ? ?//實(shí)例化枚舉實(shí)例

? ? ? ?MONDAY = new Day("MONDAY", 0);

? ? ? ?TUESDAY = new Day("TUESDAY", 1);

? ? ? ?WEDNESDAY = new Day("WEDNESDAY", 2);

? ? ? ?THURSDAY = new Day("THURSDAY", 3);

? ? ? ?FRIDAY = new Day("FRIDAY", 4);

? ? ? ?SATURDAY = new Day("SATURDAY", 5);

? ? ? ?SUNDAY = new Day("SUNDAY", 6);

? ? ? ?$VALUES = (new Day[] {

? ? ? ? ? ?MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY

? ? ? ?});

? ?}

}

可以看到,編譯后生成一個(gè)final類插爹,同時(shí)前面的七個(gè)日期定義成七個(gè)類型哄辣。同時(shí)還有兩個(gè)靜態(tài)方法请梢,分別是values()和 valueOf(),MONDAY枚舉類型對應(yīng)public static final Day MONDAY;力穗,values()方法的作用就是獲取枚舉類中的所有變量毅弧,并作為數(shù)組返回,而valueOf(String name)方法與Enum類中的valueOf方法的作用類似根據(jù)名稱獲取枚舉變量当窗,只不過編譯器生成的valueOf方法更簡潔些只需傳遞一個(gè)參數(shù)够坐。由于values()方法是由編譯器插入到枚舉類中的static方法,所以如果我們將枚舉實(shí)例向上轉(zhuǎn)型為Enum超全,那么values()方法將無法被調(diào)用咆霜,因?yàn)镋num類中并沒有values()方法,valueOf()方法也是同樣的道理嘶朱。

final變量經(jīng)常和static關(guān)鍵字一起使用蛾坯,作為常量。final類通常功能是完整的疏遏,不允許被繼承脉课。

因此枚舉類型,在調(diào)用中如果對內(nèi)部變量使用了set函數(shù)财异,那么就是對一個(gè)常量進(jìn)行了上set操作倘零,也就會導(dǎo)致所有調(diào)用的地方的值都發(fā)生了變化。

EnumSet和EnumMap

EnumSet

EnumSet是一個(gè)針對枚舉類型的高性能Set接口實(shí)現(xiàn)戳寸,但是在其中裝入的枚舉類型必須是同類型的呈驶,在EnumSet中通過bit-vector實(shí)現(xiàn),也就是一個(gè)long型疫鹊。EnumSet支持在遍歷袖瞻。

for (WeekDayEnum day:EnumSet.range(WeekDayEnum.Mon,WeekDayEnum.Sun)){

? ?System.out.println(day)

}

同時(shí)EnumSet還提供了一個(gè)獲取子集的方法:

EnumSet <WeekDayEnum> JobDays = ?EnumSet.of(WeekDayEnum.Mon,WeekDayEnum.Fri);

EnumMap

EnumMap是一個(gè)高性能的Map接口實(shí)現(xiàn),主要管理用枚舉做Key-Value的關(guān)系拆吆,內(nèi)部是通過數(shù)組方式實(shí)現(xiàn)的聋迎。

private static Map<WeekDayEnum,RainbowClolor> schema = new EnumMap<WeekDayEnum.values()[i],RainbowClolor.values()[i]>(WeekDatEnum.class);

關(guān)注測者枣耀,關(guān)注測試

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末霉晕,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子捞奕,更是在濱河造成了極大的恐慌牺堰,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件颅围,死亡現(xiàn)場離奇詭異萌焰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)谷浅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人一疯,你說我怎么就攤上這事撼玄。” “怎么了墩邀?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵掌猛,是天一觀的道長。 經(jīng)常有香客問我眉睹,道長荔茬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任竹海,我火速辦了婚禮慕蔚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘斋配。我一直安慰自己孔飒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布艰争。 她就那樣靜靜地躺著坏瞄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪甩卓。 梳的紋絲不亂的頭發(fā)上鸠匀,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機(jī)與錄音逾柿,去河邊找鬼缀棍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鹿寻,可吹牛的內(nèi)容都是我干的睦柴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼毡熏,長吁一口氣:“原來是場噩夢啊……” “哼坦敌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起痢法,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤狱窘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后财搁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蘸炸,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年尖奔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了搭儒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片穷当。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖淹禾,靈堂內(nèi)的尸體忽然破棺而出馁菜,到底是詐尸還是另有隱情,我是刑警寧澤铃岔,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布汪疮,位于F島的核電站,受9級特大地震影響毁习,放射性物質(zhì)發(fā)生泄漏智嚷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一纺且、第九天 我趴在偏房一處隱蔽的房頂上張望盏道。 院中可真熱鬧,春花似錦隆檀、人聲如沸摇天。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽泉坐。三九已至,卻和暖如春裳仆,著一層夾襖步出監(jiān)牢的瞬間腕让,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工歧斟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纯丸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓静袖,卻偏偏與公主長得像觉鼻,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子队橙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • Enum的簡介 Enum是計(jì)算機(jī)編程語言中的一種數(shù)據(jù)類型坠陈。枚舉類型` 枚舉類型很早就在計(jì)算機(jī)語言中存在了,主要被用...
    愛碼小士閱讀 1,747評論 0 1
  • 18.7.18一捐康、概述枚舉常量在類型安全性和便捷性都很有保證仇矾,如果出現(xiàn)類型問題編譯器也會提示我們改進(jìn)。除了不能繼承...
    靜心安分讀書閱讀 527評論 0 0
  • 定義枚舉 在定義枚舉類型時(shí)我們使用的關(guān)鍵字是enum解总,與class關(guān)鍵字類似贮匕,要注意,值一般是大寫的字母花枫,多個(gè)值之...
    笨笨噠2018閱讀 360評論 0 0
  • 一刻盐、什么是枚舉掏膏? 枚舉是由一組固定的常量組成的合法值。通過這一定義隙疚,我們可以看出枚舉的核心在于常量壤追,而且常量是固定...
    Roger_黃閱讀 960評論 0 4
  • Chapter 6 Enums and Annotations 枚舉和注解 JAVA supports two s...
    LaMole閱讀 809評論 0 2