Effective Java读书笔记二:枚举和注解
第30條:用enum代替int常量
當需要一組固定常量的時候,應該使用enum代替int常量,除了對于手機登資源有限的設備應該酌情考慮enum的性能弱勢之外。
第31條:用實例域代替序數
枚舉的ordinal()方法會返回枚舉常量在類型中的數字位置, 但是盡量不要使用它,因為當重新排序后,會對客戶端造成破壞。 正確的做法是,將他保存在一個實例域中。
應該給enum添加int域,而不是使用ordinal方法來導出與枚舉關聯的序數值。(幾乎不應使用ordinal方法,除非在編寫像EnumMap這樣的基于枚舉的通用數據結構)
//WRONG public enum Fruit{APPLE, PEAR, ORANGE;public int numberOfFruit(){return ordinal() + 1;} }//RIGHT public enum Fruit{APPLE(1), PEAR(2), ORANGE(3);private final int number;Fruit(int num) {number = num;}public int numberOfFruit(){return number;} }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
第32條:用EnumSet代替位域
每個EnumSet的內容都表示為位矢量。如若底層的枚舉類型個數小于64個,則整個EnumSet就用單個long來表示,因此性能上比的上位域。
//WRONG public class Text{private static final int STYLE_BOLD = 1 << 0;private static final int STYLE_ITALIC = 1 << 1;private static final int STYLE_UNDERLINE = 1 << 2;public void applyStyles(int styles) {...} } //use text.applyStyles(STYLE_BOLD | STYLE_ITALIC);//RIGHT public class Text{public enum Style{STYLE_BOLD, STYLE_ITALIC, STYLE_UNDERLINE}public void applyStyles(Set<Style> styles) {...} //這里不使用EnumSet<Style>參數是因為考慮到某些客戶端可能會傳遞一些其他的Set實現 } //use text.applyStyles(EnumSet.of(STYLE_BOLD, STYLE_ITALIC));- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
第33條:用EnumMap代替序數索引
序數索引是指依賴于枚舉成員在枚舉中的序數來進行數組索引,如:
//定義了植物類,其中植物又分為水果,蔬菜,樹木三種 public class Plant{public enum Type { Fruit, Vegetables, Tree}private final String name;private final Type type;Plant(String name, Type type){this.name = name;this.type = type;} }Set<Plant>[] plants = (Set<Plant>[]) new Set[Plant.Type.valuse().lenght]; //根據植物的類型,分別把所有的植物放入三個set中 for(int i = 0; i < plant.lenght; i++){plant[i] = new HashSet<Plant>(); }for(Plant p : garden){ //garden里放了所有的植物plant[p.type.ordinal()].add(p) //反面教材:利用了枚舉的序數來得到想要的數組索引,用戶在其他地方可以不使用ordinal函數,而直接使用int值來訪問,就可能出錯 }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
應該使用EnumMap來實現,EnumMap內部是采用數組實現的,具有Map的豐富功能和類型安全以及數組 的效率:
Map<Plant.Type, Set<Plant>> plants = new EnumMap<Plant.Type, Set<Plant>>(Plant.Type.class); //構造函數需要 鍵 類型的Class對象 //根據植物的類型,分別把所有的植物放入三個set中 for(Plant.Type type : Plant.Type.valuse()){plant.put(type, new HashSet<Plant>); }for(Plant p : garden){ //garden里放了所有的植物plant.get(p.type).add(p) //用戶必須使用正確的鍵值來訪問,即Type類型 }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
當需要多維關系時,可以使用EnumMap<…, EnumMap<…>>
第34條:用接口模擬可以伸縮的枚舉
1、如果讓一個 枚舉類型 去擴展另一個 枚舉類型,利用語言的特性,幾乎是不可能的?
2、枚舉的可擴展性,到最后都證明不是一個好點子.
由于在Java中enum不是可擴展的,在某些情況下,可能需要對枚舉進行擴展,比如操作類型(+-*/等),就可以考慮:?
1.定義一個接口,比如public interface Operation{…};?
2.使枚舉繼承接口:比如public enum BasicOperation implements Operation{…}?
3.使用時的API寫成接口(比如,T extends Enum & Operation),而不是實現(比如BasicOperation )
- 1
- 1
4.當需要擴展BasicOperation枚舉時,就可以另寫一個枚舉,且implements接口Operation
第35條:注解優先于命名模式
優先使用注解來表面針對某些程序元素的特定信息。?
注解的優勢:
第36條:堅持使用Override注解
在想要覆蓋的方法上使用Override注解,編譯器就可以幫助發現一些錯誤。可以不寫Override的特例:在具體類中不必標注你確信覆蓋了抽象方法聲明的方法(雖然這么做也沒有什么壞處)。
第37條:用標記接口實現類型
標記分為標記接口和標記注解。
標記接口:沒有包含方法聲明的接口,只是指明某個類實現了具有某種屬性的接口。比如Serializable接口,通過實現這個接口,類表明它的實例可以被寫到ObjectOutputStream。。
標記接口與標記注解的最終要的區別在于:?
標記接口可以在編譯時就檢查到相應的類型問題,而標記注解則要到運行時。
標記接口優勢:
如果注解類型利用 @Target(ElementType.TYPE) 標記,則它可以被應用到任何類或者接口上
標記注解優勢:
使用:
《Effective Java中文版 第2版》PDF版下載:?
http://download.csdn.net/detail/xunzaosiyecao/9745699
作者:jiankunking 出處:http://blog.csdn.net/jiankunking
from:?http://blog.csdn.net/jiankunking/article/details/54844842
總結
以上是生活随笔為你收集整理的Effective Java读书笔记二:枚举和注解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Effective Java读书笔记一:
- 下一篇: java美元兑换,(Java实现) 美元