陷阱 - 返回 null 而不是抛出异常

一些 Java 程序员普遍厌恶抛出或传播异常。这导致代码如下:

public Reader getReader(String pathname) {
    try {
        return new BufferedReader(FileReader(pathname));
    } catch (IOException ex) {
        System.out.println("Open failed: " + ex.getMessage());
        return null;
    }

}

那有什么问题呢?

问题是 getReadernull 作为一个特殊值返回,表示 Reader 无法打开。现在需要测试返回值以查看它是否在使用之前是 null。如果省略测试,结果将是一个 NullPointerException

这里实际上有三个问题:

  1. IOException 很快被捕捉了。
  2. 此代码的结构意味着存在泄漏资源的风险。
  3. 使用 null 然后返回,因为没有真正的Reader 可用于返回。

事实上,假设异常确实需要像这样早点发现,有几种方法可以返回 null

  1. 可以实现 NullReader 类; 例如,API 的操作就像读者已经处于文件结束位置一样。
  2. 使用 Java 8,可以将 getReader 声明为返回 Optional<Reader>