该类和 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() 方法而被终止的情况。关于该类的更多知识后续将详细介绍。