Junit單元測試遇見的一個列舉型別的坑(列舉型別詳解)
Enum的簡介
Enum是計算機程式語言中的一種資料型別。列舉型別
列舉型別很早就在計算機語言中存在了,主要被用來將一組相似的值包含進一種型別中,這種型別的名稱被定義成獨一無二的型別描述符,這就是列舉型別。
在java語言中,列舉型別是一個完整功能的類,允許開發者給列舉型別新增方法和屬性,同時也可以提供介面。同時Java也為Enum提供了高質量的實現,比如comparable和Serializable介面.
- 其中:Comparable 是排序介面,如果一個Java類有這個介面,那麼只能說明這個類支援排序。即然實現Comparable介面的類支援排序,假設現在存在“實現Comparable介面的類的物件的List列表(或陣列),則該List列表(或陣列)可以通過 Collections.sort(或 Arrays.sort)進行排序。“實現Comparable介面的類的物件”可以用作“有序對映(如TreeMap)”中的鍵或“有序集合(TreeSet)”中的元素,而不需要指定比較器。 Serializable介面的物件轉換成一個字元序列,並能夠在以後將這個位元組序列完全恢復為原來的物件。而且這個過程是可以通過網路完成的,也就是說序列化機制能夠自動彌補不同作業系統之間差異。*
Enum的定製
通過類的定義,可以給Enum一些複雜的功能,例如下面程式碼給Enum增加屬性:
public enum DrinkEnum{
1. // 酒 2. Wine("a cup of wine "); 3. //橙汁 4. Oragen_Juice("a cup of oragen juice") 5. //Enum物件的drink_class屬性 6. private String drink_class; 7. //列舉物件建構函式 8. private DrinkEnum(String drink){ 9. this.drink_class=drink; 10. } 11. //列舉物件的drink_class屬性 12. public String getDrink(){ 13. return this.drink_class; 14. }
Enum的一些坑
-
1 Enum 不支援public和protected修飾符的構造方法,因此建構函式一定要是private或者friendly的,這也就約束了列舉物件是無法在程式中通過直接呼叫建構函式進行初始化的。
-
2 Enum的值是通過執行期構造出來的物件表示的,因此在叢集環境下,每個jvm構造出同義物件,但是在做布林運算的時候有可能有問題,因此要格外注意。在對Enum進行比較的時候,使用值比對。
Enum的原理
在使用enum建立列舉型別後,編譯器會為其生成一個對應的列舉類,這個類繼承與java.lang.Enum。舉例如下:
1. enum Day { 2. MONDAY, TUESDAY, WEDNESDAY, 3. THURSDAY, FRIDAY, SATURDAY, SUNDAY 4. }
編譯後會變成Day.class,那麼反編譯後看到如下:
1. final class Day extends Enum
2. {
3. //編譯器為我們新增的靜態的values()方法
4. public static Day[] values()
5. {
6. return (Day[])$VALUES.clone();
7. }
8. //編譯器為我們新增的靜態的valueOf()方法,注意間接呼叫了Enum也類的valueOf方法
9. public static Day valueOf(String s)
10. {
11. return (Day)Enum.valueOf(com/zejian/enumdemo/Day, s);
12. }
13. //私有建構函式
14. private Day(String s, int i)
15. {
16. super(s, i);
17. }
18. //前面定義的7種列舉例項
19. public static final Day MONDAY;
20. public static final Day TUESDAY;
21. public static final Day WEDNESDAY;
22. public static final Day THURSDAY;
23. public static final Day FRIDAY;
24. public static final Day SATURDAY;
25. public static final Day SUNDAY;
26. private static final Day $VALUES[];
27. static
28. {
29. //例項化列舉例項
30. MONDAY = new Day("MONDAY", 0);
31. TUESDAY = new Day("TUESDAY", 1);
32. WEDNESDAY = new Day("WEDNESDAY", 2);
33. THURSDAY = new Day("THURSDAY", 3);
34. FRIDAY = new Day("FRIDAY", 4);
35. SATURDAY = new Day("SATURDAY", 5);
36. SUNDAY = new Day("SUNDAY", 6);
37. $VALUES = (new Day[] {
38. MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
39. });
40. }
41. }
可以看到,編譯後生成一個final類,同時前面的七個日期定義成七個型別。同時還有兩個靜態方法,分別是values()和 valueOf(),MONDAY列舉型別對應public static final Day MONDAY;,values()方法的作用就是獲取列舉類中的所有變數,並作為陣列返回,而valueOf(String name)方法與Enum類中的valueOf方法的作用類似根據名稱獲取列舉變數,只不過編譯器生成的valueOf方法更簡潔些只需傳遞一個引數。由於values()方法是由編譯器插入到列舉類中的static方法,所以如果我們將列舉例項向上轉型為Enum,那麼values()方法將無法被呼叫,因為Enum類中並沒有values()方法,valueOf()方法也是同樣的道理。
final變數經常和static關鍵字一起使用,作為常量。final類通常功能是完整的,不允許被繼承。
因此列舉型別,在呼叫中如果對內部變數使用了set函式,那麼就是對一個常量進行了上set操作,也就會導致所有呼叫的地方的值都發生了變化。
如果對軟體測試、介面測試、自動化測試、效能測試、LR指令碼開發、面試經驗交流。感興趣可以175317069,群內會有不定期的發放免費的資料連結,這些資料都是從各個技術網站蒐集、整理出來的,如果你有好的學習資料可以私聊發我,我會註明出處之後分享給大家。
EnumSet和EnumMap
EnumSet
EnumSet是一個針對列舉型別的高效能Set介面實現,但是在其中裝入的列舉型別必須是同類型的,在EnumSet中通過bit-vector實現,也就是一個long型。EnumSet支援在遍歷。
1. for (WeekDayEnum day:EnumSet.range(WeekDayEnum.Mon,WeekDayEnum.Sun)){
2. System.out.println(day)
3. }
同時EnumSet還提供了一個獲取子集的方法:
1. EnumSet <WeekDayEnum> JobDays = EnumSet.of(WeekDayEnum.Mon,WeekDayEnum.Fri);
EnumMap
EnumMap是一個高效能的Map介面實現,主要管理用列舉做Key-Value的關係,內部是通過陣列方式實現的。
1. private static Map<WeekDayEnum,RainbowClolor> schema = new EnumMap<WeekDayEnum.values()[i],RainbowClolor.values()[i]>(WeekDatEnum.class);