Effective Java for Android

Android 版《Effective Java》

翻譯原文 Effective Java for Android

《Effective Java》是公認的Java最重要的書籍之一,該書介紹了如何編寫長期可維護的代碼,同時又兼顧效率。Android應(yīng)用是使用Java進行開發(fā),那是否意味著這本書中的建議都可以應(yīng)用到Android開發(fā)中?并未如此。有些人認為書中的大部分建議無法應(yīng)用到Android開發(fā)世界中。因為Android沒有優(yōu)化Java的所有特性(比如說:枚舉,本地化等)或是手機設(shè)備的限制(比如 Dalvik/ART 與桌面JVM的差異),書中的一部分內(nèi)容無法應(yīng)用到Android開發(fā)中。盡管如此,書中的大部分范式還是可以經(jīng)過少許的修改或者直接使用,用以構(gòu)建更加健康的、清晰的、可維護的代碼基礎(chǔ)。

這篇博客將嘗試關(guān)注書中那些我認為對于Android開發(fā)比較重要的條目。

Force non-instantiability

如果你不希望對象被new創(chuàng)建,可以使用私有的構(gòu)造函數(shù)。對于那些只有靜態(tài)方法的工具類特別有用。

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

Static Factories

不使用new以及構(gòu)造函數(shù),而是使用靜態(tài)工廠方法(以及私有構(gòu)造函數(shù))。這些工廠方法被賦予名字,不要求每次都返回一個新的實例,并且可以根據(jù)要求來返回不同的子類型。

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

Builder

當(dāng)你有一個對象的構(gòu)造函數(shù)包含3個以上的參數(shù)時,使用Builder來構(gòu)建對象。這樣做有些繁瑣,但是更容易擴展并且可讀性更好。如果你要創(chuàng)建一個數(shù)據(jù)類(value class), 那么考慮下使用Auto Value。

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();

Avoid mutability

不可變,是說對象在其整個生命周內(nèi)保持一致。對象中所有的必要數(shù)據(jù)都在創(chuàng)建時提供,這種方式有簡潔性,線程安全,可分享(shareability)等優(yōu)點。

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

把所有的類都設(shè)計成不可變是不可能的。盡管如此,還是要把類盡可能的設(shè)計成不可變(比如,private final域以及final 類)。手機上創(chuàng)建類會有更多開銷,所以要適量。

Static member classes

如果你定義的內(nèi)部類不依賴于外部類,不要忘記把它定義成靜態(tài)的。否則的話,內(nèi)部類的每個實例都會包含一個外部類的引用。

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

Generics(almost)everywhere

我們應(yīng)該感謝Java提供的類型安全(請參見JavaScript)。盡可能的避免使用原始類型或類。泛型提供了在編譯時確保類型安全的機制。

// DON'T
List movies = Lists.newArrayList();
movies.add("Hello!");
[...]
String movie = (String) movies.get(0);

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

不要忘記可是在方法的參數(shù)以及返回中使用泛型

// DON'T
List sort(List input) {
    [...]
}

// DO
<T> List<T> sort(List<T> input) {
    [...]
}

再復(fù)雜一點的情況,你可以使用通配符來擴展類型范圍。

// 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"));
    [...]
}

Return empty

當(dāng)不得不返回沒有數(shù)值的list或者collection時,不應(yīng)該返回null。返回一個空集合,使其指向一個比較簡單接口(不需要編寫文檔或者使用非空返回注解功能),這樣避免了引發(fā) NullPointException。盡量返回同一個集合,而不是創(chuàng)建一個新的。

// 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"));
    [...]
}

No + String

需要鏈接少量的String時,可以使用+。 當(dāng)需要鏈接大量的字符串變量時,不要使用,因為性能很差。這個時候使用StringBuilder來代替。

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

Recoverable exceptions

我個人不喜歡在檢查到錯誤是拋出異常,但是你要這樣做的話,要保證異常是可檢測的,并且異常的捕獲者可以修復(fù)這個錯誤。

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

總結(jié)

這份列表并不是書中建議的全部列表,也不是簡短的深度解讀。這是一份備忘錄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,941評論 25 709
  • 概述: 這篇文章的目的是作為這篇博文的開源版本,而netcyrax是該指南的原始文章的唯一作者。 請在下面添加您自...
    心隨身走閱讀 334評論 0 3
  • 前言 人生苦多,快來 Kotlin ,快速學(xué)習(xí)Kotlin! 什么是Kotlin? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,686評論 9 118
  • 最近在重新學(xué)習(xí)一遍C++的內(nèi)容,由于C++的指針部分比較復(fù)雜,而且很抽象所以大學(xué)的時候?qū)W過的東西現(xiàn)在也忘了好多。這...
    哈啰于先生閱讀 6,470評論 0 2
  • Rida/蕭娜再一眼,候鳥已過,夕陽滿坡 昨日他鄉(xiāng)遇竹馬,三兩件舊事請奏:紅泥小爐烹紅豆,相思煮不透;麥芽釀成宴賓...
    蕭娜閱讀 654評論 29 9

友情鏈接更多精彩內(nèi)容