京东自营 + 国补 iPhone 历史最低价          国家补贴 享8折

Java 的 几个实用技巧


从写Java到现在,最让我记忆犹新的,反而是些一开始觉得很聪明、后来却碰了一鼻子灰的用法。

就说这个双括号初始化吧,早年我也觉得挺优雅:

List<String> list = new ArrayList<String>() {{
    add("A");
    add("B");
}};

直到有一次排查一个内存泄漏,发现是因为这个匿名内部类隐式持有了外部类的引用,在某个长生命周期的对象里用多了,GC都收不掉。还有序列化的时候,经常报一些莫名其妙的错误。现在除非写临时测试代码,否则一律改用List.of()或者老老实实add

2. ThreadLocal——线程池里的“幽灵数据”

这个坑估计不少人都踩过。当时在做用户上下文传递,图省事用了ThreadLocal存登录信息:

private static final ThreadLocal<User> context = new ThreadLocal<>();

// 登录后塞进去
context.set(currentUser);

// 业务里直接取
User user = context.get();

在单元测试里一切正常,一上线用了Tomcat线程池就出灵异事件——用户A偶尔会看到用户B的数据。原因就是线程被复用了,上次的ThreadLocal没清。后来学乖了,一定配套写try-finally清理:

try {
    context.set(user);
    doBusiness();
} finally {
    context.remove(); // 这句不能少
}

3. Optional——别拿它当普通对象用

刚出Optional那会儿,我也喜欢到处套:

public Optional<String> findName() {
    return Optional.ofNullable(someNullableValue);
}

但后来看到有人这么写:

Optional<User> user = Optional.ofNullable(getUser());
if (user.isPresent()) {
    // ...
}

这不就是变相的if (user != null)吗?完全没发挥Optional的意图。我现在觉得,Optional的核心意义是声明“这个方法可能没有返回值”,逼着调用方处理空情况,而不是在业务逻辑里到处判断isPresent()

4. try-with-resources——Java 7最好的礼物

以前关资源是每个Java人的噩梦:

InputStream is = null;
try {
    is = new FileInputStream("file");
    // 读文件
} finally {
    if (is != null) {
        try { is.close(); } catch (IOException e) { /* 吞了? */ }
    }
}

现在一句搞定:

try (InputStream is = new FileInputStream("file")) {
    // 自动关,异常也不会漏
}

而且从JDK 9开始,还能用已有的变量:

Reader reader = new StringReader("text");
try (reader) { // 不用再声明新变量
    // ...
}

这种改进才是实实在在的福利。

5. switch表达式——从劝退到真香

以前的switch写得我头疼,特别是忘了break的时候:

展开阅读全文

本文系作者在时代Java发表,未经许可,不得转载。

如有侵权,请联系nowjava@qq.com删除。

编辑于

关注时代Java

关注时代Java