FilterWriter
是 Java I/O 体系中字符输出流的核心抽象类,位于 java.io
包下。它与字节流体系中的 FilterOutputStream
形成对称设计,共同构成 Java I/O「装饰器模式」的基础框架。本文将结合源码,从类结构、设计模式、核心方法实现等角度,深入解析 FilterWriter
的设计思想。
public abstract class FilterWriter extends Writer {
protected Writer out; // 被装饰的底层字符输出流
protected FilterWriter(Writer out) {
super(out); // 调用父类 Writer 的构造方法(传递锁对象)
this.out = out;
}
}
FilterWriter
继承自抽象类 Writer
(所有字符输出流的基类),强制要求子类实现字符输出的核心能力。protected Writer out
持有一个底层字符输出流实例(如 FileWriter
、StringWriter
),这是装饰器模式的核心特征——通过组合而非继承扩展功能。abstract
,无法直接实例化,必须由子类(如 BufferedWriter
、OutputStreamWriter
)提供具体实现。装饰器模式的核心是在不修改原始对象的前提下,动态叠加功能。其关键要素包括:
FilterWriter
如何体现装饰器模式?FilterWriter
继承自 Writer
,与所有字符输出流(如 FileWriter
)共享 write
、flush
、close
等核心方法,确保装饰器与原始流可以无缝替换。write(int c)
、flush()
)默认直接调用底层流 out 的对应方法(如 out.write(c)
),将基础字符输出功能委托给被装饰对象。BufferedWriter
重写 write
方法添加缓冲逻辑),符合「开闭原则」(对扩展开放,对修改关闭)。FilterWriter
的方法设计高度统一,核心逻辑均是将请求转发给底层流 out
,以下是关键方法的详细分析:
write(int c)
:写入单个字符public void write(int c) throws IOException {
out.write(c); // 直接委托给底层流
}
该方法将单个字符的写入操作直接转发给底层流 out
。子类可重写此方法添加过滤逻辑(例如 CipherWriter
可在此加密字符)。
write(char[] cbuf, int off, int len)
:写入字符数组的一部分public void write(char cbuf[], int off, int len) throws IOException {
out.write(cbuf, off, len); // 委托给底层流的同名方法
}
此方法将字符数组的指定区间写入操作委托给底层流。默认实现不做任何额外处理,子类(如 BufferedWriter
)会重写此方法,先将数据写入缓冲区,待缓冲区满时再批量写入底层流,减少 I/O 次数。
write(String str, int off, int len)
:写入字符串的一部分public void write(String str, int off, int len) throws IOException {
out.write(str, off, len); // 委托给底层流处理字符串
}
字符串是字符的高级抽象,此方法将字符串的区间写入操作直接转发给底层流。例如 OutputStreamWriter
(FilterWriter
的子类)会在此方法中完成字符到字节的编码转换。
flush()
:刷新缓冲区public void flush() throws IOException {
out.flush(); // 委托底层流刷新
}
刷新操作的本质是将缓冲区中未写入的字符强制输出到目标设备。FilterWriter
的默认实现直接调用底层流的 flush
,子类(如 BufferedWriter
)会先将自定义缓冲区的数据写入底层流,再触发底层流的刷新。
close()
:关闭流public void close() throws IOException {
out.close(); // 直接关闭底层流
}
关闭流时,FilterWriter
直接调用底层流的 close
方法释放资源。由于 Writer
实现了 AutoCloseable
接口,可通过 try-with-resources
语法自动关闭。
BufferedWriter
为例BufferedWriter
是 FilterWriter
的典型子类,通过添加字符缓冲区优化写操作效率:
public class BufferedWriter extends FilterWriter {
private char[] cb; // 字符缓冲区
private int nChars; // 缓冲区容量
private int nextChar; // 下一个写入位置
public BufferedWriter(Writer out, int sz) {
super(out);
if (sz <= 0) throw new IllegalArgumentException("Buffer size <= 0");
this.cb = new char[sz];
this.nChars = sz;
}
public void write(char[] cbuf, int off, int len) throws IOException {
if (len == 0) return;
// 如果数据量超过缓冲区大小,直接刷新缓冲区并写入底层流
if (len >= nChars) {
flushBuffer();
out.write(cbuf, off, len);
return;
}
// 数据量较小:写入缓冲区
int b = off;
int t = off + len;
while (b < t) {
int d = nextChar + (b - off);
if (d >= nChars) { // 缓冲区剩余空间不足,先刷新
flushBuffer();
d = b - off;
}
int l = Math.min(t - b, nChars - d);
System.arraycopy(cbuf, b, cb, d, l);
b += l;
nextChar += l;
}
}
private void flushBuffer() throws IOException {
if (nextChar > 0) {
out.write(cb, 0, nextChar); // 批量写入底层流
nextChar = 0; // 重置缓冲区指针
}
}
}
通过重写 write
方法,BufferedWriter
优先将字符写入内部缓冲区,仅当缓冲区满或数据量过大时,才调用底层流的 write
方法。这种批量写入机制显著减少了 I/O 操作次数,提升了字符输出效率。
装饰器模式的普适性:
FilterWriter
与 FilterOutputStream
共同构成 Java I/O 的装饰器基础框架,分别处理字符流与字节流的功能扩展。这种设计使得开发者可以通过嵌套装饰器(如 new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt")))
)灵活组合「缓冲+编码转换+文件输出」等功能,避免了继承链膨胀。
抽象类的职责分离:
FilterWriter
作为抽象装饰器,仅定义基础行为(转发请求),将具体功能扩展(如缓冲、编码)交给子类实现。这种「抽象基类定义框架,子类实现细节」的设计,符合「单一职责原则」。
I/O 流的可组合性:
由于所有过滤字符流都继承自 FilterWriter
,开发者可以根据需求动态叠加功能。例如:
Writer writer = new FileWriter("data.txt"); // 基础文件写入流
Writer bufferedWriter = new BufferedWriter(writer); // 缓冲功能
Writer utf8Writer = new OutputStreamWriter( // 编码转换功能(字节转字符)
new FileOutputStream("data.txt"),
StandardCharsets.UTF_8
);
FilterWriter
是 Java 字符输出流体系中装饰器模式的核心实现,通过「继承+组合」的方式,为字符流的功能扩展提供了灵活的基础框架。理解其设计思想,不仅能深入掌握 Java I/O 流的运行机制,更能学会如何通过设计模式解决实际开发中「动态功能扩展」的问题。