适用于 Android 开发的 Effective Java 已翻译 100%

oschina 投递于 2017/03/14 16:02 (共 6 段, 翻译完成于 03-15)
阅读 2631
收藏 75
3
加载中

Effective Java” 被许多人看做是编写高效且可维护的 Java 代码的重要指导书之一。Android 使用 Java 开发是否意味着里面的建议都要用上?不完全是。 有些人认为这本书给出的大多数建议不适用于 Android 开发。在我看来,情况并非如此。 我认为这本书的一些部分是不适用,不管是因为不是所有 Java 功能都已优化到能与 Android 一起使用(例如枚举、序列化等),还是因为是移动设备的限制例如 Dalvik/ART 表现不同于桌面版的 JVM)。 但不管怎样,本书中的大多数范式还是可以在稍作修改后或直接使用,从而构建一个更健康、更简洁和更易维护的代码库。

Tocy
Tocy
翻译于 2017/03/14 16:13
1

这篇博客整合了我在开发 Android 应用时,从 Effective Java 中学习到的重要内容。对于那些读过这本书的人,这篇文章就当是重新回顾一下,对于那些(还)没有阅读它的人,可以把这篇文章当作试读。

强制非实例化(non-instantiability)

如果你不想使用 new 关键字来创建对象,强制它使用私有构造函数。 这对那些仅包含静态函数的工具类尤其有用。

class MovieUtils {
    private MovieUtils() {}    static String titleAndYear(Movie movie) {
        [...]
    }
}
Tocy
Tocy
翻译于 2017/03/14 16:22
0

静态工厂

用静态工厂方法 (同时私有化构造器) 代替使用 new 和构造函数。这些工厂方法有自己的名称,不需要每次都返回一个对象的新实例,还可以根据需要返回不同的子对象。

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

[更新] 我们的读者 @stsdema28 提供了一个有用的提示:静态工厂方法会造成测试困难。如果遇到这种问题,需要使用在测试中使用可模拟的非静态工厂(或者一个可实现的假接口)。

构建器(Builder)

如果你的对象需要超过 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();
边城
边城
翻译于 2017/03/14 22:00
0

避免易变性

不可变对象在它的整个生命周期都保持不变。这类对象所需要的数据都是在它创建的时候提供给它的。使用不可变对象有一些优点,比如简单、线程安全以及可共享。

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 字段和 private class)。在移动端创建对象开销很大,所以注意不要过度创建。

静态成员类

如果你定义了一个不依赖于外部类的内部类,千万别忘了把它定义成静态的。如果不这样做,会导致每个内部类的实例都持有外部类的引用。

class Movie {
    [...]
    static class MovieAward {
        [...]
    }
}
边城
边城
翻译于 2017/03/14 22:11
0

随处可见的泛型

Java 提供了类型安全支持。尽量避免使用原始类型或对象类型。在大多数情况下,泛型提供了编译时让代码类型安全的机制。

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

别忘了你可以在方法的参数和返回值中使用泛型:

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

返回空值

当必须返回空的 list/collection 时避免使用 null。返回空的集合会使接口变简单(不需要为空返回的函数写文档或注释)并可以避免随机的 NPE。建议返回同一个空集合而不是重新创建一个。

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();
}
Tocy
Tocy
翻译于 2017/03/14 16:55
0

可恢复的异常

我不赞成抛出指示错误的异常,但如果你这样做了,请确保异常可受检查且可恢复:

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

结论

这个列表并没有罗列书中的所有建议,也不是对书中某个建议的深度解析,而仅仅是对部分有用建议的摘录而已。

Tocy
Tocy
翻译于 2017/03/14 16:28
0
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(6)

边城
边城

引用来自“花间_拾零”的评论

null处理 Options.of(list);
Android 对 Java8 支持得如何?
媚竹风
媚竹风
字符串连接什么情况下只能使用 StringBuilder或者 StringBuffer,什么情况下可以使用 + 进行连接,你真的搞懂了吗?对于使用"+"进行连接的时候,jvm进行的优化,你知道吗?其它文章中的错误就不枚举了,希望博主本着负责的态度,多多求证,彻底搞懂了在发表出来
方开金
方开金
java中确实有许多优化点不适合android
wkh
wkh
禁止非机动车通行,大杰轮子声卡车近远。
黑色星期五
对于枚举的看法 应该已经过时了
无畏的老巨人
无畏的老巨人
null处理 Options.of(list);
返回顶部
顶部