Effective Java 筆記(二)

泛型
NO.23 - NO.29java

枚舉和註解
枚舉類型(Enumerated Type)很早就出如今編程語言中,它被用來將一組相似的值包含到一種類型當中。而這種枚舉類型的名稱則會被定義成獨一無二的類型描述符,在這一點上和常量的定義類似。不過相比較常量類型,枚舉類型能夠爲申明的變量提供更大的取值範圍。
舉個例子來講明一下,若是但願爲彩虹描繪出七種顏色,你能夠在 Java 程序中經過常量定義方式來實現。android

Public static class RainbowColor { 
   // 紅橙黃綠青藍紫七種顏色的常量定義
   public static final int RED = 0; 
   public static final int ORANGE = 1; 
   public static final int YELLOW = 2; 
   public static final int GREEN = 3; 
   public static final int CYAN = 4; 
   public static final int BLUE = 5; 
   public static final int PURPLE = 6; 
}

使用的時候,你能夠在程序中直接引用這些常量。可是,這種方式仍是存在着一些問題。
類型不安全
因爲顏色常量的對應值是整數形,因此程序執行過程當中頗有可能給顏色變量傳入一個任意的整數值,致使出現錯誤。
沒有命名空間
因爲顏色常量只是類的屬性,當你使用的時候不得不經過類來訪問。
一致性差
由於整形枚舉屬於編譯期常量,因此編譯過程完成後,全部客戶端和服務器端引用的地方,會直接將整數值寫入。這樣,當你修改舊的枚舉整數值後或者增長新的枚舉值後,全部引用地方代碼都須要從新編譯,不然運行時刻就會出現錯誤。
類型無指意性
因爲顏色枚舉值僅僅是一些無任何含義的整數值,若是在運行期調試時候,你就會發現日誌中有不少魔術數字,但除了程序員自己,其餘人很難明白其奧祕。
爲 了改進 Java 語言在這方面的不足彌補缺陷,5.0 版本 SDK 發佈時候,在語言層面上增長了枚舉類型。枚舉類型的定義也很是的簡單,用 enum 關鍵字加上名稱和大括號包含起來的枚舉值體便可,例如上面提到的彩虹顏色就能夠用新的 enum 方式來從新定義:程序員

enum RainbowColor { RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, PURPLE }

從上面的定義形式來看,彷佛 Java 中的枚舉類型很簡單,但實際上 Java 語言規範賦予枚舉類型的功能很是的強大,它不只是簡單地將整形數值轉換成對象,而是將枚舉類型定義轉變成一個完整功能的類定義。這種類型定義的擴展容許開 發者給枚舉類型增長任何方法和屬性,也能夠實現任意的接口。另外,Java 平臺也爲 Enum 類型提供了高質量的實現,好比默認實現 Comparable 和 Serializable 接口,讓開發者通常狀況下不用關心這些細節。
回到本文的主題上來,引入枚舉類型到底可以給 咱們開發帶來什麼樣好處呢?一個最直接的益處就是擴大 switch 語句使用範圍。5.0 以前,Java 中 switch 的值只可以是簡單類型,好比 int、byte、short、char, 有了枚舉類型以後,就可使用對象了。這樣一來,程序的控制選擇就變得更加的方便,看下面的例子:編程

// 定義一週七天的枚舉類型            
public enum WeekDayEnum { Mon, Tue, Wed, Thu, Fri, Sat, Sun } 

// 讀取當天的信息
WeekDayEnum today = readToday(); 

// 根據日期來選擇進行活動
switch(today) { 
 Mon: do something; break; 
 Tue: do something; break; 
 Wed: do something; break; 
 Thu: do something; break; 
 Fri: do something; break; 
 Sat: play sports game; break; 
 Sun: have a rest; break; 
}

對於這些枚舉的日期,JVM 都會在運行期構形成出一個簡單的對象實例一一對應。這些對象都有惟一的 identity,相似整形數值同樣,switch 語句就根據此來進行執行跳轉。
NO.30 用enum代替int常量
NO.31 用實例域代替序數
NO.32 用EnumSet代替位域
NO.33 用EnumMap代替序數索引
NO.34 用接口模擬可伸縮的枚舉數組

Java Annotation 及幾個經常使用開源項目註解原理簡析安全

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewBinder {
    int id() default -1;
    String method() default "";
    String type() default "";
}

@interface是用於自定義註解的,它裏面定義的方法的聲明不能有參數,也不能拋出異常,而且方法的返回值被限制爲簡單類型、String、Class、emnus、@interface ,和這些類型的數組。服務器

註解@Target也是用來修飾註解的元註解,它有一個屬性ElementType也是枚舉類型,值 爲:ANNOTATION_TYPE,CONSTRUCTOR ,FIELD,LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER和TYPE,如 @Target(ElementType.METHOD) 修飾的註解表示該註解只能用來修飾在方法上。jvm

@RetentionRetention註解表示須要在什麼級別保存該註釋信息,用於描述註解的生命週期,它有一個RetentionPolicy類型的value,是一個枚舉類型,它有如下的幾個值:編程語言

(1)用@Retention(RetentionPolicy.SOURCE)修飾的註解,指定註解只保留在源文件當中,編譯成類文件後就把註解去掉;
(2)用@Retention(RetentionPolicy.CLASS)修飾的註解,指定註解只保留在源文件和編譯後的class 文件中,當jvm加載類時就把註解去掉;
(3)用@Retention(RetentionPolicy.RUNTIME )修飾的註解,指定註解能夠保留在jvm中,這樣就可使用反射獲取信息了。
默認是RUNTIME,這樣咱們才能在運行的時候經過反射獲取並作對應的邏輯處理。
NO.35 註解優先於命名模式
NO.36 堅持使用Override註解
NO.37 用標記接口定義類型ide

方法
NO.38 檢查參數的有效性
可使用斷言assert進行有效性檢查,但assert須要顯式開啓,不推薦使用斷言。
NO.39 必要時進行保護性拷貝
NO.40 謹慎設計方法簽名
(1)謹慎地選擇方法的名稱
(2)不要過於追求提供便利的方法
(3)避免過長的參數列表(同類型的長參數序列格外有害)
a.分解成多個方法
b.建立輔助類
c.採用Builder模式
d.對於參數類型,要優先使用接口而不是類
e.對於boolean參數,要優先使用兩個元素的枚舉類型。
NO.41 慎用重載
NO.42 慎用可變參數
有時候,有必要編寫須要1個或者多個某種類型參數的方法,而不是須要0個或者多個。

static int min(int firstArg,int...remainingArgs) {
        int min = firstArgs;
        for (int arg : remainingArgs) {
            if (arg < min)
                min = arg;
        }
        return min;
    }

NO.43 返回零長度的數組或集合,而不是null
NO.44 爲全部導出的API元素編寫文檔註釋

相關文章
相關標籤/搜索