BufferedReader的继承机制核心是单继承自Reader类,并通过实现特定接口与组合底层字符流,形成“基础抽象类 + 功能增强实现”的结构,确保符合Java IO流的统一规范。

其继承与关联关系可分为以下3个层级

1. 顶层父类:Reader

BufferedReader直接继承自Java IO的抽象基类 java.io.Reader 。 Reader 是所有字符输入流的顶层抽象,定义了字符读取的核心方法(如 read() 、 read(char[]) 、 close() 等),BufferedReader需重写这些方法以实现“缓冲读取”的增强逻辑,同时保证与其他字符流(如FileReader)的接口一致性。

2. 自身实现:重写父类方法 + 维护缓冲属性

作为 Reader 的子类,BufferedReader并未额外继承其他类(Java单继承特性),而是通过自身实现完成功能增强:

- 重写 Reader 的 read() 、 read(char[], int, int) 等方法,加入“缓冲区检查-预读取-指针移动”的逻辑(如之前提到的缓冲机制)。

- 新增便捷方法,如 readLine() (读取整行字符,基于缓冲区实现换行符识别),这是父类 Reader 未定义的扩展功能。

- 内部维护 private char[] buf (字符缓冲区数组)、 private int pos (缓冲区当前读取位置)等属性,支撑缓冲逻辑。

3. 关联底层流:通过组合而非继承

BufferedReader不继承具体的底层字符流(如InputStreamReader、FileReader),而是通过组合方式关联:

- 构造方法需传入一个 Reader 类型的参数(即底层源字符流),将其作为数据读取的源头。

- 缓冲逻辑仅负责“批量预读-缓存”,实际从数据源(文件、网络等)读取原始字符的操作,仍委托给传入的底层 Reader 完成,实现职责分离与灵活适配。

具体来说,这个“8KB字符缓冲区”的作用流程是:
 
1. 初始化“容器”:创建BufferedReader时,会在内存中开辟一块空间,专门用来存放8192个字符(默认大小,可通过构造方法 BufferedReader(Reader in, int size) 自定义大小,如设为16384字符即32KB)。

2. 批量“囤货”:当你第一次调用 read() 读取字符时,BufferedReader不会直接去底层流拿1个字符,而是一次性把“8KB容器”装满(从底层流读取8192个字符存入容器)。

3. 按需“取用”:之后每次调用 read() ,都直接从这个“容器”里取1个字符,直到容器里的字符被取完。

4. 空了再“补货”:当容器空了,BufferedReader才会再次去底层流读取一批字符,把容器重新装满,重复“囤货-取用”的过程,直到整个流读取完毕。

使用填写FileReader的BufferedReader和直接使用FileReader的区别:

- BufferedReader + FileReader:BufferedReader 内部维护一个字符缓冲区(默认8KB),会一次性从 FileReader 读取大量字符存入缓冲区,后续读取直接从缓冲区获取,仅在缓冲区为空时才再次调用 FileReader 读取。这种“批量预读”大幅减少了对磁盘(FileReader 底层依赖的存储设备)的直接读写次数,显著降低 IO 开销,效率更高。

除了基础的字符读取,BufferedReader 还提供了  readLine()  方法,可直接读取一整行字符(自动识别  \n 、 \r\n  等换行符),无需手动处理换行逻辑,功能更丰富。

适用于所有需要读取字符的场景,尤其是大文件读取、频繁读取、需按行读取的场景(如日志解析、配置文件读取),是实际开发中的首选方式。

- 直接用 FileReader:每次调用  read() (读单个字符)或  read(char[]) (读字符数组)时,都会直接触发对磁盘的 IO 操作,即使只读取1个字符也需访问磁盘。频繁的磁盘 IO 是性能瓶颈,尤其在读取大文件时,效率远低于前者。
​仅适用于极小文件读取、对效率无要求的简单场景(如读取几行的配置文件),因性能问题,很少在实际项目中单独使用。

更多推荐