中总结Android开发的一些建议在编写易于维护且高效的长时间运行的Java代码方面,《Effective Java》被许多人视为最重要的书籍之一。Android使用的是Java语言,这意味着本书中给出的所有建议都适用于Android,对吧?答案是:不一定。有人认为本书给出的大部分建议都不适合Android开发。不是这样,在我看来。我认为本书的部分内容不适用,因为并非所有Java特性都针对Android进行了优化(例如枚举、序列化等),并且因为移动设备有其自身的局限性(例如Dalvik/ART的行为与JVM不同).尽管如此,本书中的大多数示例都可以在很少修改或无需修改的情况下使用,并且可以有助于构建更健康、更清洁和更易于维护的代码库。本文重点介绍本书中我认为对Android开发至关重要的知识点。对于看过本书的人来说,本文可以作为对书中提到的原理/知识的复习。对于那些(还)没有读过它的人,这篇文章让他们有机会尝试一下这本书。强制不可实例化如果你不想使用new关键字创建对象,强制使用私有构造函数。这对于只包含静态方法的实用程序类更有用。ListlatestMovies(){if(db.query().isEmpty()){returnCollections.emptyList();}[...]}静态工厂不要使用_new_关键字和构造函数,使用静态工厂方法(和一个私有构造函数)。这些工厂方法是有名字的,不需要每次都返回一个新的对象实例,可以根据需要返回不同的子类型。classMovie{[...]publicstaticMoviecreate(Stringtitle){returnnewMovie(title);}}[更新]读者@stsdema28提出了一个有用的建议:使用静态工厂会使测试变得困难。如果是这样,请考虑在测试时使用非静态工厂进行模拟(或可以实现的工厂接口)。Builders当你需要三个以上的构造参数时,使用Builder来构造这个对象。写起来可能有点冗长,但它的扩展性和阅读性都很好。如果您要创建值类型,请考虑AutoValue。classMovie{staticBuildernewBuilder(){returnnewBuilder();}staticclassBuilder{Stringtitle;BuilderwithTitle(Stringtitle){this.title=title;returnthis;}Moviebuild(){returnnewMovie(title);}}privateMovie(Stringtitle){[…]}}//像这样使用:Moviematrix=Movie.newBuilder().withTitle("TheMatrix").build();避免可变性不可变对象在其整个生命周期中保持不变。所有必需的数据都在对象创建时提供。这种方法有几个优点,例如简单性、线程安全性和可共享性。classMovie{[...]Moviesequel(){returnMovie.create(this.title+"2");}}//用这个:MovietoyStory=Movie.create("ToyStory");MovietoyStory2=toyStory.sequel();很难使每个类不可变。对于这种情况,让您的类尽可能不可变(例如,使用私有最终字段、最终类声明)。在移动设备上创建对象的成本更高,所以不要过度。静态成员类如果你定义了一个不依赖于外部类的内部类,不要忘记将其定义为static。如果不这样做,将导致内部类的每个实例都引用外部类。classMovie{[...]staticclassMovieAward{[...]}}泛型(几乎)无处不在Java提供了类型安全,我们应该对此心存感激(看看JS)。尽量避免使用原始类型(rawtypes)或对象类型。在大多数情况下,泛型提供了一种在编译时使代码类型安全的机制。//DON'TListmovies=Lists.newArrayList();movies.add("Hello!");[...]Stringmovie=(String)movies.get(0);//DOListmovies=Lists.newArrayList();movies.add("你好!");[...]Stringmovie=movies.get(0);不要忘记您可以在函数参数和返回值中使用泛型。//DON'TListsort(Listinput){[...]}//DOListsort(Listinput){[...]}为了更灵活,您可以使用有界通配符来扩展可接受类型的范围。//Readstufffromcollection-use"extends"voidreadList(ListmovieList){for(Moviemovie:movieList){System.out.print(movie.getTitle());[...]}}//Writestufftocollection-使用"super"voidwriteList(ListmovieList){movieList.add(Movie.create("Se7en"));[...]}当必须返回空列表/集合时返回void(list/collection),避免空值。返回一个空集合会产生一个更简单的接口(不需要通过文档注释和声明返回null的函数),并避免意外的空指针异常。***返回一个相同的空集合,而不是创建一个新集合。ListlatestMovies(){if(db.query().isEmpty()){returnCollections.emptyList();}[...]}不要使用+来连接String如果要连接多个字符串,则+运营商也许。但是永远不要将它用于大量的字符串连接,性能会很糟糕。***请改用StringBuilder。StringlatestMovieOneLiner(Listmovies){StringBuildersb=newStringBuilder();for(Moviemovie:movies){sb.append(movie);}returnsb.toString();}我不喜欢通过抛出异常错误指定的可恢复异常,但如果这样做,请确保检查了异常并且异常的捕获器可以从错误中恢复。ListlatestMovies()throwsMo??viesNotFoundException{if(db.query().isEmpty()){thrownewMoviesNotFoundException();}[...]}不是简短的深入评论描述。只是有用建议的备忘单:)。