在编写恒久运行下既易于维护又能保持高效的 Java 代码这方面 ,《 Effective Java 》被许多人看做最重要的书之一。 Android 利用的是 Java 语言,这就意味着这本书中所有给出的发起必然都是合用与 Android 的,对吗?谜底是:不必然。有些人认为这本书给出的大大都发起都不合用于 Android 开拓。在我看来,也并非如此。我认为这本书中有一部门是不合用的,因为不是所有的 Java 特性都是为了用于 Android 而优化的(好比列举,序列化等等),也因为移动设备存在自身的限制(好比 Dalvik/ART 表示和 JVM 差异)。尽量如此,这本书中的大大都典型照旧可以或许不加修改可能少量修改地被利用,并可以或许有助于成立一个越发康健、清洁和可维护的代码库。
本文存眷于这本书中我认为对付 Android 开拓至关重要的常识点。对付阅读过这本书的人来说,本文可以作为书中提到的原则/常识的回首。对付那些(今朝)还没有读过的人来说,本文可以给他们一个时机去实验下这本书。
强制不行实例化
假如你不但愿利用 new 要害字来建设一个工具,那就强制利用私有结构器(private constructor)。这对付仅包括静态要领的东西类来说越发有用。
List<Movie> latestMovies() { if (db.query().isEmpty()) { return <strong>Collections.<em>emptyList</em>()</strong>; } [...] }
静态工场
不要利用 _new_ 要害字和结构器,利用静态工场要领(以及一个私有的结构器)。这些工场要领是定名的,不需要每次都返回一个新的工具实例,并且可以按照需要返回差异的子范例。
class Movie { [...] public static Movie <strong>create</strong>(String title) { return new Movie(title); } }
【更新】读者 @ stsdema28 提出了一个有用的发起:利用静态工场会使得测试变得坚苦。假如这样的话,不妨思量利用一个非静态的工场用于在测试时举办模仿(可能一个可以或许实现的工场接口)。
Builders
当你有需要三个以上的结构参数时,利用 Builder 去结构这个工具。写起来大概有点烦琐可是这样伸缩性和可读性都很好。假如你建设的是值范例,思量 AutoValue。
class Movie { static Builder newBuilder() { return new Builder(); } static class <strong>Builder</strong> { String title; Builder <strong>withTitle</strong>(String title) { this.title = title; return this; } Movie <strong>build</strong>() { return new Movie(title); } } private Movie(String title) { [...] } } // Use like this: Movie matrix = Movie.<em>newBuilder</em>().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();
或者很难做到每个类都不行变。对付这种环境,尽大概使你的类变得不行变(好比利用 private final 字段,劳务派遣管理系统,final 类声明)。在移动设备上建设工具价钱越发昂贵,因此不要太过利用。
静态成员类
假如你界说了一个不依赖于外部类的内部类,别忘了将其界说为静态的。不这么做的话会导致每个内部类的实例城市拥有对外部类的引用。
class Movie { [...] <strong>static</strong> class MovieAward { [...] } }
泛型(险些)无处不在
Java 提供了范例安详的特性,我们应对此心怀谢谢(看看JS吧)。只管制止利用原始范例 (raw types)可能工具范例。泛型大大都环境下都提供了让你的代码在编译时范例安详的机制。
// DON'T List movies = Lists.newArrayList(); movies.add("Hello!"); [...] String movie = (<strong>String</strong>) movies.get(0); // Do List <<strong>String</strong>> movies = Lists.newArrayList(); movies.add("Hello!"); [...] String movie = movies.get(0);
别忘了你能在函数的参数和返回值中利用泛型。
// DON'T List sort(List input) { [...] } // DO <T> List<T> sort(List<T> input) { [...] }
为了越发机动你可以利用 bounded wildcards 来拓展可接管的范例的范畴。
// Read stuff from collection - use "extends" void readList(List<? <strong>extends</strong> Movie> movieList) { for (Movie movie : movieList) { System.<em>out</em>.print(movie.getTitle()); [...] } } // Write stuff to collection - use "super" void writeList(List<? <strong>super</strong> Movie> movieList) { movieList.add(Movie.create("Se7en")); [...] }