该类和 FilterInputStream 类类似,都是抽象装饰类。
FilterOutputStream 类也位于 java.io 包中,它继承自 OutputStream 类,是一个抽象装饰器类。如下图:
从图可以得知,它是很多 InputStream 增强流的基类,其主要用途是为其他输出流添加额外的功能。FilterOutputStream 本身并不直接实现数据的输出操作,而是将具体的输出任务委托给被装饰的输出流,同时在这个过程中可以添加一些额外的处理逻辑,以此来增强输出流的功能。
源码如下:
public class FilterOutputStream extends OutputStream { /** * 将被过滤的底层输出流 */ protected OutputStream out; /** * 流是否已关闭,默认初始化为 false。 */ private volatile boolean closed; /** * 锁对象,用于防止对 “closed” 实例变量进行竞争 */ private final Object closeLock = new Object(); // 传递被过滤流到内部 public FilterOutputStream(OutputStream out) { this.out = out; } @Override public void write(int b) throws IOException { out.write(b); } @Override public void write(byte[] b) throws IOException { write(b, 0, b.length); } @Override public void write(byte[] b, int off, int len) throws IOException { if ((off | len | (b.length - (len + off)) | (off + len)) < 0) throw new IndexOutOfBoundsException(); for (int i = 0 ; i < len ; i++) { write(b[off + i]); } } @Override public void flush() throws IOException { out.flush(); } @Override public void close() throws IOException { // 该方法将在后续详细介绍 } }
通过分析源码,FilterOutputStream 和 FilterInputStream 类一样,将所有请求都委托给了被增强的类,这里是 OutputStream。
但是,FilterOutputStream 类的 close() 方法却是一个列外,该方法代码还不少,如下:
/** * 关闭此输出流并释放与该流相关的任何系统资源。 * * 如果未关闭,FilterOutputStream 的 close() 方法会调用其 flush() 方法刷新流, * 然后调用其底层输出流的 close() 方法。 * * @throws IOException 如果出现 I/O 错误 * @see java.io.FilterOutputStream#flush() * @see java.io.FilterOutputStream#out */ @Override public void close() throws IOException { // 如果流已经关闭,直接返回 if (closed) { return; } // 同步处理,设计 closed 为 true,表示已经关闭 synchronized (closeLock) { if (closed) { return; } closed = true; } Throwable flushException = null; // 存放刷新抛出的异常对象 try { flush(); // 刷新流,避免部分数据在缓存,没有落地 } catch (Throwable e) { flushException = e; // 刷新出现异常 throw e; } finally { // 如果刷新没有异常,则调用底层流的 close() 关闭流 if (flushException == null) { out.close(); } else { // 如果刷新存在异常 try { out.close(); } catch (Throwable closeException) { // 评估 flushException 相对于 closeException 的可能优先级 // 对异常进行合理的合并与抛出,从而保证程序异常处理的准确性和完整性。 if ((flushException instanceof ThreadDeath) && !(closeException instanceof ThreadDeath)) { // 将指定的异常附加到为了抛出此异常而被抑制的异常列表中 flushException.addSuppressed(closeException); throw (ThreadDeath) flushException; } if (flushException != closeException) { // 将 flushException 异常添加到 closeException 异常的抑制的异常列表中 closeException.addSuppressed(flushException); } throw closeException; } } } }
上面代码,重写了 close() 方法,其主要意图是安全且正确地关闭流,同时处理在刷新(flush)和关闭(close)操作中可能出现的异常。
在关闭流时,先确保流没有被重复关闭,然后执行刷新操作将缓冲区数据输出,最后关闭底层流。同时,对刷新和关闭操作中可能出现的异常进行了细致的处理,保证在出现异常时能够保留所有异常信息,便于后续的调试和问题排查。
ThreadDeath 类位于 java.lang 包中,它继承自 Error 类。在 Java 里,Error 通常代表那些程序无法处理的严重问题。ThreadDeath 用于表示线程因调用 Thread.stop() 方法而被终止的情况。关于该类的更多知识后续将详细介绍。