我想知道下面的代码是否正确关闭了finally块中的InputStream
InputStream is = new FileInputStream("test");
try {
for(;;) {
int b = is.read();
...
}
} finally {
try {
is.close();
} catch(IOException e) {
}
}
如果在is.close()期间发生异常,则在is.close()期间发生异常会被忽略/抑制吗?
答案 0 :(得分:15)
最好的方法是使用Java 7并使用try with resources,或者手动执行相同的操作,并将关闭中的异常添加为抑制异常。
Pre Java 7: 如果你抛出自定义异常,你可以像在Java 7中那样添加压缩异常(在你的异常创建字段列表中被禁止并在关闭操作中放置异常,在处理异常时,也可以查看它。 如果你不能这样做,我不知道什么比记录它更好。
例子: 来自Java tutorials
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
但更好的形式是:
static String readFirstLineFromFile(String path) throws IOException {
try (FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr)) {
return br.readLine();
}
}
这种方式即使FileReader的创建成功但BufferedReader的创建失败(例如内存不足),FileReader也将被关闭。
答案 1 :(得分:7)
如果由于任何其他原因导致try块的执行突然完成,则执行finally块。然后有一个选择: 如果finally块正常完成,则try语句突然完成,原因是R. 如果finally块因为S而突然完成,则try语句突然完成,原因是S(并且原因R被丢弃)。
所以你是对的,你将失去原来的例外。
解决方案可能是如此防御地编写你的finally块,如果finally块失败,那么它是一个更大的意外(值得传播),而不是try catch块出现异常。
因此,例如,如果在您尝试关闭它时该流可能为null,请检查它:
InputStream is = new FileInputStream("test");
try {
for(;;) {
int b = is.read();
...
}
} finally {
try {
if( is!=null ) {
is.close();
}
} catch(IOException e) {
}
}
在Java 7中,Alpedar的解决方案当然是可行的。
答案 2 :(得分:6)
您可以使用https://commons.apache.org/proper/commons-io/
中的IOUtils关闭它 public void readStream(InputStream ins) {
try {
//do some operation with stream
} catch (Exception ex) {
ex.printStackTrace();
} finally {
IOUtils.closeQuietly(ins);
}
}
答案 3 :(得分:2)
is.close()的异常将被禁止,并且is.read()的异常将是传播的异常。
答案 4 :(得分:2)
使用您发布的代码:
is.close()
抛出IOException
,它就会被丢弃,原始异常会传播。is.close()
抛出其他内容(RuntimeException
或Error
),则会传播该内容并丢弃原始异常。使用Java 7,关闭InputStream而不丢失原始异常的正确方法是使用try-with-resources statement:
try (InputStream is = new FileInputStream("test")) {
for(;;) {
int b = is.read();
// ...
}
}
在Java 7之前,你做的很好,除了你可能想要捕获所有异常,而不仅仅是IOException
。
答案 5 :(得分:1)
如果在int b = is.read();
点发生异常,则根据您的代码示例,异常将在调用链的上方提升。
请注意,finally块仍将执行,如果Inputstream
无效,则会抛出另一个异常,但此异常将被“吞噬”,这可能是可接受的,具体取决于您的用例。
编辑:
根据你问题的标题,我想补充一点,我认为你所拥有的是好的。您可能还需要添加一个catch
块来显式处理(或者可能包装)第一个try
块中的任何异常,但允许任何IO异常升高也是可以接受的 - 这实际上取决于你的API。 IO异常升高可能会或可能不会被接受。如果是,那么你没关系 - 如果不是那么你可能想用更适合你的程序的东西来处理/包装IO异常。
答案 6 :(得分:0)
下一个解决方案怎么样:
InputStream is = new FileInputStream("test");
Exception foundException=null;
try {
for(;;) {
int b = is.read();
...
}
} catch (Exception e){
foundException=e;
}
finally {
if(is!=null)
try {
is.close();
} catch(IOException e) {
}
}
//handle foundException here if needed
答案 7 :(得分:0)
如果在is.close()期间发生异常,则在is.close()期间发生异常会被忽略/抑制吗?
是。在close()中有一个异常的catch块,它不会重新抛出异常。因此,它不会被传播或重新播放。
答案 8 :(得分:0)
这是帮助您了解问题的示例, 如果您在try-catch块中声明扫描程序,它将给编译器警告资源未关闭。 所以要么在本地制作,要么只在try()
import java.util.InputMismatchException;
import java.util.Scanner;
class ScanInt {
public static void main(String[] args) {
System.out.println("Type an integer in the console: ");
try (Scanner consoleScanner = new Scanner(System.in);) {
System.out.println("You typed the integer value: "
+ consoleScanner.nextInt());
} catch (InputMismatchException | ArrayIndexOutOfBoundsException exception) {
System.out.println("Catch Bowled");
exception.printStackTrace();
}
System.out.println("----------------");
}
}