Android 中的 Effective Java(速查表)
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