Android 中的 Effective Java(速查表)

451007609 8年前發布 | 4K 次閱讀 Java 安卓開發 Android開發 移動開發

Effective Java 是一本被廣泛認可的著作,它指明了在寫 Java 代碼時兼顧 可維護性效率 的方式。Android 也是使用 Java 來開發的,這意味著前書中的 所有 建議仍舊可用,真的是這樣嗎?并不盡然。 某些 同學 認為書中的“大部分”建議都不適用于 Android 開發,但我認為并不是這樣。我承認書中的部分建議確實不適用,因為并非所有 Java 特性都有針對 Android 優化(比如說 枚舉 ,序列化等等),或者是因為移動設備的局限 (例如 Dalvik / ART )。 不管怎樣,書中的 大部分 規范是稍微修改下甚至不修改就可以直接用的,以便構建更 魯棒 ,簡潔且更可維護的代碼庫。

本文試圖聚焦于原書中我認為在 Android 開發時最重要的一些條目。對于那些讀過此書的人,本文也許能幫助你回憶起這些條目,對于那些(還)沒有讀過的人,本文能夠讓他們品嘗到一絲原書的韻味。

強制不可實例化

如果你不希望一個對象通過關鍵字 new 來創建,那么強制讓它的 構造方法私有 。這尤其對一些只包含靜態方法的工具類有用。

class MovieUtils {
  private MovieUtils() {}

    static String titleAndYear(Movie movie) {
        [...]
    }
}

靜態工廠方法

不要使用 new 關鍵字和構造方法創建對象,而應當使用靜態工廠方法(和私有構造方法)。這些工廠方法具有名字,不需要每次返回一個新的對象實例,它們可以依據需求返回不同的子類型對象。

class Movie {
    [...]
    public static Movie create(String title) {
        return new Movie(title);
    }
}

創建者模式

當對象的構造方法參數不小于 3 個時,可以考慮創建者模式。這可能需要更多行的代碼,但拓展性和可讀性會很好。如果你正創建一個實體類,考慮使用 AutoValue 。

class Movie {
    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();

避免可變性

不可變性是指對象在其整個生命周期內一直保持不變。應將對象中所有必要的數據在其創建時就賦值。這個做法有許多好處,比如簡潔化,線程安全以及可共享性等。

class Movie {
    [...]
    Movie sequel() {
        return Movie.create(this.title + " 2");
    }
}
// Use like this:
Movie toyStory = Movie.create("Toy Story");
Movie toyStory2 = toyStory.sequel();

很難將所有的類都設為不可變類,如果是這樣的話,盡可能多地讓你的類變成不可變類(例如私有化常量以及不可繼承類)。在移動設備中創建對象代價更高,因此不要濫用它。

靜態成員類

如果你定義了一個不依賴外部類的內部類,不要忘記將其定義為靜態的。否則將會導致每一個內部類對象都會持有對外部類的引用。

class Movie {
    [...]
  static class MovieAward {
        [...]
    }
}

泛型 (幾乎) 無處不在

Java 提供了類型檢查,我們應當對此感激(看看 JS )。盡量避免使用無類型或 Object 類型。泛型機制,大多數情況下保障了編譯時的類型檢查。

// 不要這樣做
List movies = Lists.newArrayList();
movies.add("Hello!");
[...]
String movie = (String) movies.get(0);

// 這樣做
List<String> movies = Lists.newArrayList();
movies.add("Hello!");
[...]
String movie = movies.get(0);

不要忘記你能在方法中對參數和返回值使用泛型

// 不要這樣做
List sort(List input) {
    [...]
}

// 這樣做
<T> List<T> sort(List<T> input) {
    [...]
}

想更靈活的話,你可以使用 bounded wildcards 來擴展你接受類型的范圍。

// 從集合中讀取 Stuff - 使用 "extends"
void readList(List<? extends Movie> movieList) {
    for (Movie movie : movieList) {
        System.out.print(movie.getTitle());
        [...]
    }
}

// 向集合中寫入 Stuff - 使用 "super"
void writeList(List<? super Movie> movieList) {
    movieList.add(Movie.create("Se7en"));
    [...]
}

返回空值

當你方法的返回類型為 list/collecion 時,返回空值時要避免返回 null 。返回一個空的集合類型,這會使得你 簡化接口 (沒有必要寫文檔來聲明方法返回值為 null)并且 避免空指針異常 。就返回那個集合的空值,而不是再創建一個。

List<Movie> latestMovies() {
    if (db.query().isEmpty()) {
        return Collections.emptyList();
    }
    [...]
}

不要用 “+” 來連接 String

必須要拼接一系列字符串時,可能會使用 + 連字符。永遠不要用它來拼接大量字符串,這樣的性能真的很差,考慮使用 StringBuilder 來代替。

String latestMovieOneLiner(List<Movie> movies) {
StringBuilder sb = new StringBuilder();
    for (Movie movie : movies) {
        sb.append(movie);
    }
    return sb.toString();
}

Recoverable exceptions

我個人不喜歡拋出異常來指示錯誤,但是如果你這樣做,確保這個異常被檢查,確保這個 異常被捕獲到

List<Movie> latestMovies() throws MoviesNotFoundException {
    if (db.query().isEmpty()) {
throw new MoviesNotFoundException();
    }
    [...]
}

結論

這份列表絕不是書中給出建議的完整列表,也不是全書完整深入陳述的濃縮,這篇文章更像是一些有用建議的速查表 :)

 

來自:http://www.jianshu.com/p/79e9f60d9dba

 

 本文由用戶 451007609 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!