【问题标题】:is a java scanner closed when an exception is thrown?抛出异常时是否关闭了 java 扫描程序?
【发布时间】:2014-10-29 10:05:29
【问题描述】:

如果我有一个抛出 FilenotFoundException 的方法,因为我正在使用 Scanner 对象来读取文件,如果错误实际上被抛出,扫描器对象是否被关闭,或者我在处理异常时仍然需要这样做?

我知道当我在我的方法中使用 try-catch-finally 块写入来处理异常时,我会关闭扫描仪对象,但如果我必须在另一个捕获异常的对象的方法中执行此操作,我将无权访问扫描仪对象。

请保持解释简单...显然我是 java 新手(以及一般的 OO)。

【问题讨论】:

    标签: java exception-handling


    【解决方案1】:

    假设你这样做:

      Scanner scanner = new Scanner(new File("/file/does/not/exist"));
    

    并且构造函数抛出FileNotFoundException。首先要注意的是构造函数不返回Scanner 对象。相反,new 表达式将异常终止,并且不会发生对scanner 的赋值。控制最终将在某个异常处理程序中结束,该异常处理程序将无法引用scanner,因为它超出了范围。

    所以回答你的问题:

    如果错误确实被抛出,扫描器对象是否被关闭,或者我在处理异常时仍然需要这样做?

    如果FileNotFoundException被构造函数抛出,则Scanner没有Scanner对象...所以你不需要关闭它。

    但是,根据您编写代码的方式,您可能会到达处理程序或 finally 块,而完全不知道是否抛出了异常,是否在构造函数中抛出异常,或者在构造函数完成后。处理这个问题的方法取决于您使用的 Java 版本。在 Java 7 之前,这个成语类似于@Sangeeth 的回答。对于 Java 7 及更高版本,您可以这样写:

    try (Scanner scanner = new Scanner(new File(path))) {
        //your code here
    } catch (FileNotFoundException e) {
        //log it
    }
    

    请注意,“try-with-resources”语法有一个隐含的finally,它会在try 开头声明的每个(自动关闭)资源上自动调用close()。这免除了您在各种可能的成功和失败案例中关闭资源的繁琐代码的责任。


    事实上,我们可以更深入地了解这一点。 Scanner 构造函数调用FileInputStream 来打开文件,这就是抛出 FileNotFoundException 的地方。反过来,这将调用本机 open 方法来实际打开文件。如果此过程中出现问题(并引发异常),则构造函数有责任确保在允许异常传播之前释放所有资源(例如关闭本机流)。

    它必须以这种方式工作,因为失败的构造函数不返回任何内容,并且它们不能依赖堆栈中更远的东西知道如何在特定异常处理程序中释放资源。

    【讨论】:

      【解决方案2】:

      如果您使用这样的代码 Scanner scanner = new Scanner(new File("C:/abc.txt")); 如果是抛出异常,scanner对象本身不会被创建,所以不需要关闭它。

      但最好的编码方式如下所示。你可以在 finally 块中关闭。

      Scanner scanner=null;
      try
      {
          scanner = new Scanner(new File(path));
          //your code here
      }
      catch(FileNotFoundException e)//either catch or throw out
      {
         //log it
      }
      finally
      {
          if(null !=scanner)
          {
              scanner.close();
          }
       }
      

      【讨论】:

        【解决方案3】:

        new Scanner(File) 时如果找不到文件,甚至不会打开底层的FileInputStream

        最好在 finally 块中关闭扫描仪。如果扫描仪已经关闭,那么关闭调用将无效。

        或者您可以尝试try-with-resources 构造,如果发生异常,它将自动关闭资源。

        【讨论】:

        • try-with-resources 似乎是最好的方法,因为它需要更少的代码
        • @superbob 这是最好的方法,不仅仅是“更少的代码”:)。
        【解决方案4】:

        我猜你应该在 finally 块中关闭扫描器对象,无论你是否捕获异常。

        【讨论】:

          猜你喜欢
          • 2015-05-07
          • 1970-01-01
          • 1970-01-01
          • 2011-01-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-07
          相关资源
          最近更新 更多