如何从 try-with-resources 中捕获异常?

How to catch exceptions from try-with-resources?

虽然 try-with-resources 特性处理了 AutoClosable 对象本身的所有功能,但我在最近的项目中遇到了一些特殊情况。

我正在使用以下方式读取文件:

try(InputStream stream = loader.getResourceAsStream("remote-config.xml"))

问题是我读取上面文件的路径是错误的。所以,我预计会出现异常 'FileNotFoundException'。现在,我知道当我使用 try-with-resources 时,我可以有 catch 块,也可以没有。另外,令我惊讶的是,我的 catch 块没有捕获到任何异常,我的日志中也没有收到任何错误。

如果try-with-resources不需要那个catch块,那为什么要加进去呢?而且,当它不存在时,是否会抛出任何异常?在第二种情况下是否向 JVM 抛出异常,我如何记录这些异常?

下面是我的代码:

    private Map<String, String> fillMappingsMap(Map<String, String> serviceToJndiNameMappings)
    {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        try(InputStream stream = loader.getResourceAsStream("remoting-config.xml"))
        {
            if (stream != null)
            {
                // logic for - read the file , fill the map to be returned.
            }
        }
        catch (IOException | ParserConfigurationException | SAXException e)
        {
            logger.error("Could not create service to JNDI Name mapping.", e);
        }
        return serviceToJndiNameMappings;
    }

If there is no need of that catch block with try-with-resources, then why can it be added there?

如果自行车上不需要辅助轮,为什么要加?

回答:因为有时需要,有时不需要。

在您的示例中,如果您需要处理来自 try with resources 的异常,那么您可以添加 catch 来处理它。 (如果需要,您甚至可以添加 finally。)

(就其价值而言,您不必 必须 在经典的 try ... 声明中有 catch。你可以有一个 finally.)


And, when it is not there, are there any exceptions thrown?

可以的。这取决于 try 做什么。


Are the exceptions thrown to the JVM in the second case ...

异常不会“抛给 JVM”。这没有意义。

但是如果你问是否会抛出异常,那么是的,它们可能会。 try 块中的代码可能会抛出未经检查的异常;例如您指定的代码“// ... 填充要返回的地图逻辑”。评论。

例如...如果存在 NPE 错误,或者如果您在填充地图时填充堆并得到 OOME。


... and how can I log those?

我怀疑在此处记录异常是否是个好主意。但是您可以通过捕获它们、记录它们然后重新抛出它们来做到这一点。

就像您正常记录异常一样...


你似乎很担心这个:

... I am going to miss a very important exception i.e. FileNotFoundException which can make anyone irritated.

你不会错过的:

  1. FileNotFoundExceptionIOException的子类所以你抓到IOException.

    肯定是抓到了
  2. 即使您没有捕捉到 IOExceptionFileNotFoundException 也是一个 checked 异常。这意味着 Java 编译器会坚持要求您要么捕获它,要么在封闭方法的“throws”子句中声明它。

  3. 终于loader.getResourceAsStream("remote-config.xml")反正不会丢FileNotFoundException!它没有打开文件。它正在获取资源的输入流。如果找不到资源,getResourceAsStream 调用 returns null 而不是抛出异常。

我建议您阅读 Oracle Java 教程中的 Catch or Specify 页。它将回答您对 Java 异常和异常处理的很多困惑。

此外,请阅读 ClassLoader.getResourceAsStreamjavadocs 以了解它在找不到资源时的行为。

getResourceAsStream 仅在资源名称为 null 时抛出 NullPointerException。

因此,如果您尝试了 getResourceAsStream(null),那么 catch 块将捕获 NullPointerException(如果在子句中提到)

唯一可以抛出的异常 getResourceAsStream(name)NullPointerException,当 namenull 时也是如此。即使找不到资源,它也不会抛出任何其他异常。

如果您希望您的代码在资源丢失时抛出 FileNotFoundException,请使用 new FileInputStream(String resourceName)(抛出所需的文件未找到异常)来加载您的资源而不是 getResourceAsStream()