【问题标题】:How to catch exceptions from try-with-resources?如何从 try-with-resources 中捕获异常?
【发布时间】:2021-07-27 11:57:48
【问题描述】:

虽然 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;
    }

【问题讨论】:

  • 有点,但它具体指的是 Autoclosable 对象上的关闭异常,而不是 FileNotFoundException 之类的特定异常。无论如何,谢谢你。我也会看看。只有当我无法捕捉到异常时我才知道这一点,这让我发疯了。我不得不做很多烦人的体力工作。
  • 你确定FileNotFoundException被抛出了吗?因为catch 子句会捕获异常,即使它不是由于close()
  • 我在 Wildfly 上部署了应用程序。最初,我尝试更改日志记录级别,认为它没有因此而被记录但没有结果。所以,我也尝试了 syso/sout。但是,一无所获。不确定它是否会像它一样工作。或者我错过了一些东西,但是我粘贴的代码是我唯一错误的,try 块中的其余实现什么都没有。即使它没有打印我放在 try 中的第一个 print 语句,说它没有进入 try。

标签: java try-catch java-7 try-with-resources


【解决方案1】:

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

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

【讨论】:

  • 是的,我想我也可以自定义流部分并检查流为空,然后根据需要抛出并记录错误。已经在我的代码中进行了更改。
  • @Ashish 不要检查stream == null 然后抛出FileNotFoundException 然后记录,我建议使用FileInputStream 来加载你的资源,这会自动抛出异常。然后在 catch 子句中,您可以根据需要捕获它并记录错误。这样可以避免 try 块内的混乱
【解决方案2】:

仅当资源名称为 null 时,getResourceAsStream 才会引​​发 NullPointerException。

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

【讨论】:

    【解决方案3】:

    如果不需要带有try-with-resources的那个catch块,那为什么可以在那里添加呢?

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

    答案:因为有时需要,而有时不需要。

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

    (对于它的价值,您不必必须在经典的 try ... 声明中使用 catch。您可以只使用 finally。)


    而且,当它不存在时,是否会抛出任何异常?

    可以的。这取决于try 的作用。


    第二种情况是否会抛出异常给JVM...

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

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

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


    ...我如何记录这些?

    我怀疑在那里记录异常是个好主意。但是你可以通过捕捉它们、记录它们然后重新扔掉它们来做到这一点。

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


    您似乎对此感到担心:

    ...我将错过一个非常重要的例外,即FileNotFoundException,它会让任何人感到恼火。

    你不会错过的:

    1. FileNotFoundExceptionIOException 的子类,所以当你捕捉到IOException 时,你肯定会捕捉到它。

    2. 即使您没有捕捉到IOExceptionFileNotFoundException 也是一个已检查 异常。这意味着 Java 编译器会坚持你要么捕获它,要么在封闭方法的“抛出”子句中声明它。

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

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

    另外,阅读javadocsClassLoader.getResourceAsStream 以了解它在找不到资源时的行为。

    【讨论】:

    • 而且,如果我没有安装它怎么办。我可以记录异常吗?我怎样才能做到这一点?通过让方法抛出一个异常并在我调用该方法的地方处理它?因为,目前我代码中的方法没有抛出我可以处理的异常,我也可以删除 catch。
    • 回答:因为有时需要,有时不需要。我会接受的。谢谢。
    • 谢谢斯蒂芬,在我的评论中,如果我只有一个 sys 来代替它,代码仍然会以相同的方式运行。依据:我在里面尝试调试的那个系统没有被命中。是的,一旦我成功进入try-with-resources,我就可以捕获异常,但是当文件无法在其路径中找到并且流变为空时发生的一个异常呢?我不知道我是否可以将其视为未经检查的异常。
    • 我不明白您对代码的描述。但是未经检查的异常的含义取决于您“认为”它是什么。 JLS 规定了已检查异常与未检查异常之间的区别。并在这里解释:docs.oracle.com/javase/tutorial/essential/exceptions/…
    猜你喜欢
    • 1970-01-01
    • 2017-03-15
    • 1970-01-01
    • 2020-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多