设计意图:装饰者模式
FilterInputStream 与 FilterOutputStream 是 Java IO 中装饰者模式的核心抽象:
- 持有被装饰流引用(
in/out)。
- 将所有读写操作委托给被装饰流。
- 子类可在委托前后插入额外逻辑(缓冲、数据类型转换、格式化输出等)。
FilterInputStream 源码解析 (JDK 1.7+)
public class FilterInputStream extends InputStream {
protected volatile InputStream in; // 被装饰流
protected FilterInputStream(InputStream in) { this.in = in; }
// 所有读操作直接委托
public int read() throws IOException { return in.read(); }
public int read(byte[] b) throws IOException { return read(b, 0, b.length); }
public int read(byte[] b, int off, int len) throws IOException { return in.read(b, off, len); }
public long skip(long n) throws IOException { return in.skip(n); }
public int available() throws IOException { return in.available(); }
public void close() throws IOException { in.close(); }
// mark/reset 委托
public synchronized void mark(int readlimit) { in.mark(readlimit); }
public synchronized void reset() throws IOException { in.reset(); }
public boolean markSupported() { return in.markSupported(); }
}
关键点:
volatile 保证 in 引用可见性。
- 构造器
protected,仅供子类调用。
- 无额外逻辑,纯透明委托。
主要子类功能
| 子类 | 核心增强 |
BufferedInputStream | 内部维护 byte[] 缓冲区,减少底层读调用;支持 mark/reset。 |
DataInputStream | 提供 readInt()、readUTF() 等按机器无关格式读取基本类型;配合 DataOutputStream 实现跨平台数据交换。 |
LineNumberInputStream (已废弃) | 行号统计,建议用 LineNumberReader。 |
PushbackInputStream | 支持 unread() 回退字节,用于词法分析器。 |
FilterOutputStream 源码解析
public class FilterOutputStream extends OutputStream {
protected OutputStream out;
public FilterOutputStream(OutputStream out) { this.out = out; }
public void write(int b) throws IOException { out.write(b); }
public void write(byte[] b) throws IOException { write(b, 0, b.length); }
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]); // 逐字节委托
}
public void flush() throws IOException { out.flush(); }
public void close() throws IOException {
try { flush(); } catch (IOException ignored) {}
out.close();
}
}
注意:write(byte[], off, len) 默认实现是循环调用 write(int),子类(如 BufferedOutputStream)通常重写为批量写入以提升性能。
主要子类功能
| 子类 | 核心增强 |
BufferedOutputStream | 内部缓冲区,批量刷新,重写 write(byte[], off, len) 高效拷贝。 |
DataOutputStream | 提供 writeInt()、writeUTF() 等,配合 DataInputStream 读写基本类型。 |
PrintStream | 自动 flush、不抛异常、提供 print/println 格式化输出,System.out 即实例。 |
典型组合用法
// 带缓冲的数据读写
try (DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(new FileOutputStream("data.bin")))) {
dos.writeInt(42);
dos.writeUTF("hello");
}
try (DataInputStream dis = new DataInputStream(
new BufferedInputStream(new FileInputStream("data.bin")))) {
int i = dis.readInt(); // 42
String s = dis.readUTF(); // hello
}
装饰链:FileOutputStream → BufferedOutputStream → DataOutputStream,各司其职,灵活组合。
源码阅读建议
- 从
FilterInputStream/OutputStream 理解委托结构。
- 对比
BufferedInputStream 与 BufferedOutputStream 的缓冲区管理差异。
- 研究
DataInputStream/OutputStream 如何处理字节序(大端序)与 UTF-8 编码。
- 关注
close() 链式关闭机制,理解 try-with-resources 的自动资源管理原理。
- 上一篇文章: Gradle 任务配置深度指南:配置阶段与执行阶段、依赖管理、任务排序
- 下一篇文章: Java Web 前端基础速查手册:HTML、CSS、JavaScript、DOM 与 BOM 核心知识点
Copyright ©
程式碼之家 All Rights Reserved