在閱讀 Java IO 包文檔時發現 FilterReader 和 FilterWriter 從未使用過,嘗試 new FilterReader() 卻報錯:Cannot instantiate the type FilterReader。查閱文檔才發現,它們均為 abstract class,必須通過繼承並實現抽象方法後才能使用。
FilterReader 繼承 Reader,作用是包裝另一個字符輸入流,在不改變原流功能的基礎上,增加過濾、轉換等額外行為。這正是裝飾器模式的經典應用。
public class FD extends FilterReader {
public FD(Reader in) {
super(in); // 必須調用父類構造函數傳入被包裝的流
}
// 此處可重寫 read() 等方法實現自定義過濾邏輯
}
public void test() throws IOException {
// 建立基礎讀取鏈:文件 -> 字節流 -> 字符流 -> 緩衝流
BufferedReader br = new BufferedReader(
new InputStreamReader(
new FileInputStream("E:/syl/1.html"), "UTF-8"
)
);
// 使用自定義過濾器包裝
FD fd = new FD(br);
// 正常讀取,底層實際由 FilterReader 委派給 BufferedReader
char[] buffer = new char[1024];
int len;
while ((len = fd.read(buffer)) != -1) {
System.out.println(new String(buffer, 0, len));
}
fd.close(); // 關閉頂層流會自動關閉底層流
}
FileInputStream in = new FileInputStream("E:/syl/1.html");
InputStreamReader inReader = new InputStreamReader(in, "UTF-8");
BufferedReader br = new BufferedReader(inReader);
FilterReader/FilterWriter 是抽象裝飾基類,不可直接實例化super(in)read()/write() 實現數據攔截、轉換、過濾等邏輯BufferedReader/BufferedWriter、PushbackReader 等若需實現「讀取時自動過濾 HTML 標籤」或「寫入時自動加密」,只需繼承 FilterReader/FilterWriter 並在 read()/write() 中加入處理邏輯,即可無縫接入現有 IO 體系,體現了組合優於繼承的設計智慧。