区别
flush会输出缓冲区内容,流可以正常使用。
close会输出缓冲区内容并且关闭流。(但是close中是否直接调用flush,甚至是否输出缓冲区内容都需要看具体实现)
flush
flush()
是java.io.Flushable
定义的方法。
当数据预存到缓冲池中时,在数据的长度满足缓冲池中的大小后,才会将缓冲池中的数据成块的发送,在发送数据过程中,末尾的数据大小不能满足缓冲池的大小。最终导致这部分的数据停留在缓冲池无法发送。此时需要手动调用flush方法
close
close()
是java.io.Closeable
定义的方法。且java.io.Closeable
继承了java.io.AutoCloseable
java.io.AutoCloseable
如何正确关闭资源
code v1.0
OutputStream fos = new FileOutputStream(new File("path"));
fos.write(11);
问题:Java无法自动回收诸如文件、socket链接等资源。需要调用close方法手动关闭。
code v1.1
OutputStream fos = new FileOutputStream(new File("path"));
fos.write(11);
fos.close();
问题:当写操作出现异常时,无法正常调用close方法
code v1.2
OutputStream fos = null;
try {
fos = new FileOutputStream(new File("path"));
fos.write(11);
} catch (Exception e) {
LOG.error("failed to write, ", e);
throw e;
} finally {
if(fos != null) {
fos.close();
}
}
问题:
如果在try语句块中抛出了异常,在控制权转移到调用栈上一层代码之前,finally块也会执行。但是在执行finally块的过程中,也可能会抛出异常。如果finally语句块也抛出了异常,那么这个异常会往上传递,而之前try语句块中的那个异常就丢失了。
因此若write方法中抛出异常e1,close方法中再次抛出异常e2时,e1被抑制导致我们无法获取到足够的有效信息。
code v1.3
Java SE 7 扩展了异常,可以将“被抑制的”异常附加到主异常上。提供相比异常嵌套更合理的解决方案
java.lang.Throwable
的扩展如下:
public final void addSuppressed(Throwable exception)
将一个被抑制的异常附加到另一个异常上,从而避免异常屏蔽。
public final Throwable[] getSuppressed()
获取添加到一个异常中的被抑制的异常。
于是可以有如下版本:
OutputStream fos = null;
Exception exception = null;
try {
fos = new FileOutputStream(new File("path"));
fos.write(11);
fos.close();
} catch (Exception e) {
exception = e;
throw e;
} finally {
if ( fos != null) {
if (exception != null) {
try {
fos.close();
} catch (Exception e) {
exception.addSuppressed(e);
}
} else {
fos.close();
}
}
}
code v1.4
为了一个简单的写操作而编写如此复杂的代码显然是不合理的。
Java SE 7 中给出了try-with-resources语法糖。
try (OutputStream fos = new FileOutputStream(new File("path"))){
fos.write(11);
}
其编译后字节码与上述v1.3版本基本一致,简化了资源释放的复杂操作。