Java未报告异常

Java未报告异常,java,exception,exception-handling,Java,Exception,Exception Handling,在学习Java时,我经常遇到这个错误。事情是这样的: InputStream in = null; try { in = new InputStream(...); // do stuff } catch (IOException e) { // do whatever } finally { if (in != null) { try { in.close(); } catch (Exception e) { } } } 未报告的异常j

在学习Java时,我经常遇到这个错误。事情是这样的:

InputStream in = null;
try {
  in = new InputStream(...);
  // do stuff
} catch (IOException e) {
  // do whatever
} finally {
  if (in != null) {
    try {
      in.close();
    } catch (Exception e) {
    }
  }
}
未报告的异常java.io.FileNotFound异常;必须被抓住或宣布被抛出。

FileNotFound只是一个例子,我见过很多不同的例子。在这种特殊情况下,导致错误的代码是:

OutputStream out = new BufferedOutputStream(new FileOutputStream(new File("myfile.pdf")));
一旦我将语句放入try/catch块中,错误总是消失,代码编译并成功运行。有时对我来说已经足够了,但有时不行

首先,我从中学习的示例并不总是使用try/catch,而且显然应该是有效的

更重要的是,有时当我将整个代码放在try/catch中时,它根本无法工作。例如,在这种特殊情况下,我需要out.close()最后{}块中;但是,如果上面的语句本身在try{}中,finally{}不会“看到”out,因此无法关闭它


我的第一个想法是导入java.io.FileNotFound或另一个相关的异常,但它没有帮助。

您所指的是,这意味着必须声明或处理它们。Java中处理文件的标准结构如下所示:

InputStream in = null;
try {
  in = new InputStream(...);
  // do stuff
} catch (IOException e) {
  // do whatever
} finally {
  if (in != null) {
    try {
      in.close();
    } catch (Exception e) {
    }
  }
}
它难看吗?当然是冗长的吗?当然Java7将使使用ARM块的情况稍微好一点,但在此之前,您必须遵守上述规定

您还可以让调用方处理异常:

public void doStuff() throws IOException {
  InputStream in = new InputStream(...);
  // do stuff
  in.close();
}
尽管如此,
close()
可能仍应包装在
finally
块中


但是上面的函数声明说这个方法可以抛出一个
IOException
。由于这是一个已检查的异常,因此此函数的调用方需要捕获它(或者声明它以便调用方能够处理它等等)。

Java的已检查异常使程序员能够解决类似的问题。(在我看来,这是一件好事,即使把虫子扫到地毯下面比较容易。)

如果发生故障,您应该采取一些适当的措施。通常,处理应该位于引发异常的不同层

应正确处理资源,其形式如下:

acquire();
try {
    use();
} finally {
    release();
}
切勿将
acquire()
放入try块中。切勿将任何内容置于
acquire()
try
之间(简单赋值除外)。不要试图在一个
finally
块中释放多个资源

因此,我们有两个不同的问题。不幸的是,Java语法混淆了这两者。编写此类代码的正确方法是:

try {
    final FileOutputStream rawOut = new FileOutputStream(file);
    try {
        OutputStream out = new BufferedOutputStream(rawOut);
        ...
        out.flush();
    } finally {
        rawOut.close();
    }
} catch (FileNotFoundException exc) {
    ...do something not being able to create file...
} catch (IOException exc) {
    ...handle create file but borked - oops...
}

“Handled”我想是指try/catch。在这种情况下,什么是“声明的”?声明的意思是在“throws”子句中添加到方法签名。在doStuff可以抛出IOException的情况下,如果在运行in.close()之前抛出异常,doStuff是否可能会返回,并且“in”资源永远不会关闭?在doStuff之外,没有用于关闭资源的句柄。如果这是真的,这是Java异常中的一个主要反模式…ARM块到底是什么?Sun网站上的一些信息:为什么不将acquire放在try块中?@BrianGordon如果你将acquire放在
try
中,即使acquire失败,你也会运行发布部分(
finally
),这是错误的现在,您可以尝试编写一些代码来检查acquire是否成功,然后再运行发行版。然而,经验表明,这通常是错误编写的(而且显然没有经过测试),因此您最好使用更简单的代码。