天天看點

從Effective Java總結一些有助安卓開發的建議

在編寫長期運作下既易于維護又能保持高效的 java 代碼這方面 ,《effective java》 被很多人看做最重要的書之一。 android 使用的是 java 語言,這就意味着這本書中所有給出的建議一定都是适用與 android 的,對嗎?答案是:不一定。

有些人認為這本書給出的大多數建議都不适用于 android 開發。在我看來,也并非如此。我認為這本書中有一部分是不适用的,因為不是所有的 java 特性都是為了用于 android 而優化的(比如枚舉,序列化等等),也因為移動裝置存在自身的限制(比如 dalvik/art 表現和 jvm 不同)。盡管如此,這本書中的大多數範例還是能夠不加修改或者少量修改地被使用,并能夠有助于建立一個更加健康、幹淨和可維護的代碼庫。

本文關注于這本書中我認為對于 android 開發至關重要的知識點。對于閱讀過這本書的人來說,本文可以作為書中提到的原則/知識的回顧。對于那些(目前)還沒有讀過的人來說,本文可以給他們一個機會去嘗試下這本書。

強制不可執行個體化

如果你不希望使用 new 關鍵字來建立一個對象,那就強制使用私有構造器(private constructor)。這對于僅包含靜态方法的工具類來說更加有用。

list<movie> latestmovies() { 

    if (db.query().isempty()) { 

        return collections.emptylist(); 

    } 

    [...] 

}  

靜态工廠

不要使用 _new_ 關鍵字和構造器,使用靜态工廠方法(以及一個私有的構造器)。這些工廠方法是命名的,不需要每次都傳回一個新的對象執行個體,而且可以根據需要傳回不同的子類型。

class movie { 

    public static movie create(string title) { 

        return new movie(title); 

【更新】讀者 @ stsdema28 提出了一個有用的建議:使用靜态工廠會使得測試變得困難。如果這樣的話,不妨考慮使用一個非靜态的工廠用于在測試時進行模拟(或者一個能夠實作的工廠接口)。

builders

當你有需要三個以上的構造參數時,使用 builder 去構造這個對象。寫起來可能有點啰嗦但是這樣伸縮性和可讀性都很好。如果你建立的是值類型,考慮 autovalue。

    static builder newbuilder() { 

        return new builder(); 

    static class builder { 

        string title; 

        builder withtitle(string title) { 

            this.title = title; 

            return this; 

        } 

        movie build() { 

            return new movie(title); 

    private movie(string title) { 

    [...]     

// use like this: 

movie matrix = movie.newbuilder().withtitle("the matrix").build();  

避免可變性

不可變對象在其整個生命周期中都保持不變。所有需要的資料都在對象建立時提供。這種方式有着多種優點,如簡單,線程安全以及可共享。

    movie sequel() { 

        return movie.create(this.title + " 2"); 

movie toystory = movie.create("toy story"); 

movie toystory2 = toystory.sequel();  

或許很難做到每個類都不可變。對于這種情況,盡可能使你的類變得不可變(比如使用 private final 字段,final 類聲明)。在移動裝置上建立對象代價更加昂貴,是以不要過度使用。

靜态成員類

如果你定義了一個不依賴于外部類的内部類,别忘了将其定義為靜态的。不這麼做的話會導緻每個内部類的執行個體都會擁有對外部類的引用。

    static class movieaward { 

        [...] 

泛型(幾乎)無處不在

java 提供了類型安全的特性,我們應對此心懷感激(看看js吧)。盡量避免使用原始類型 (raw types)或者對象類型。泛型大多數情況下都提供了讓你的代碼在編譯時類型安全的機制。

// don't 

list movies = lists.newarraylist(); 

movies.add("hello!"); 

[...] 

string movie = (string) movies.get(0); 

// do 

list<string> movies = lists.newarraylist(); 

string movie = movies.get(0);  

别忘了你能在函數的參數和傳回值中使用泛型。

list sort(list input) { 

<t> list<t> sort(list<t> input) { 

為了更加靈活你可以使用 bounded wildcards 來拓展可接受的類型的範圍。

// read stuff from collection - use "extends" 

void readlist(list<? extends movie> movielist) { 

    for (movie movie : movielist) { 

        system.out.print(movie.gettitle()); 

// write stuff to collection - use "super" 

void writelist(list<? super movie> movielist) { 

    movielist.add(movie.create("se7en")); 

傳回空(清單/集合)

當必須傳回空的清單/集合時,避免使用null。傳回一個空的集合會産生一個更簡單的接口(不需要去進行文檔注釋并聲明函數傳回值為 null),還能避免意外的空指針異常。最好傳回一個相同的空集合而不是建立一個新的。

不要用 + 連接配接 string

如果要連接配接幾個字元串,+ 操作符或許可以。但永遠不要使用它來進行大量的字元串連接配接,那樣性能會十分糟糕。最好使用 stringbuilder 來代替。

string latestmovieoneliner(list<movie> movies) { 

    stringbuilder sb = new stringbuilder(); 

    for (movie movie : movies) { 

        sb.append(movie); 

    return sb.tostring(); 

可恢複的異常

我不喜歡通過抛出異常來指明錯誤,但如果你這樣做的話,就要確定異常被檢查并且異常的捕獲者能夠從錯誤中恢複。

list<movie> latestmovies() throws moviesnotfoundexception { 

        throw new moviesnotfoundexception(); 

總結

列舉的這些不是這本書中所給出的完整建議,也不是簡短說明深入評價。隻是這些有用的建議的一紙小抄而已 :)。

作者:lazy song

來源:51cto