第23篇缓冲区数据结构 ByteBuffer系列导航《Java 100 天进阶之路》完整目录 |⬅️ 上一篇第22篇Java字符串简介 |➡️ 下一篇第24篇Java枚举类型 enum 用法待发布一、核心知识点Buffer 抽象类与子类ByteBuffer、CharBuffer、IntBuffer等ByteBuffer核心属性capacity、limit、position、mark核心方法put()、get()、flip()、rewind()、clear()、compact()直接缓冲区 vs 堆缓冲区NIONew I/O中的使用场景二、通俗讲解1分钟开心学1. 什么是 BufferBuffer是 Java NIO 中用于存储数据的容器可以理解为一块可以读写的内存区域并带有一套指针系统来管理读写位置。最常用的是ByteBuffer。2. 四个核心属性capacity容量创建后不可变。limit读写的极限位置。position下一个要读/写的位置索引。mark标记位置可用reset()返回。3. 两种模式写模式刚创建时position 0limit capacity往里面put数据。读模式调用flip()后limit position原写到的位置position 0然后get数据。生活类比缓冲区就像一个水池。capacity是水池总容量。你在水池里倒水写position是水面高度。倒完后你标记一下现在的水位flip然后开始从底部取水读。取水时不能超过之前的水位limit。4. 直接缓冲区 vs 堆缓冲区堆缓冲区allocate()内存分配在 JVM 堆上受 GC 管理数据拷贝到 native 内存时多一次复制。直接缓冲区allocateDirect()内存分配在系统本机内存native heap减少一次拷贝适合大文件、网络传输但分配和释放成本高。三、实操代码案例 场景说明场景使用ByteBuffer实现一个简单的“写数据 → 读数据”流程。importjava.nio.ByteBuffer;importjava.nio.charset.StandardCharsets;publicclassByteBufferDemo{publicstaticvoidmain(String[]args){// 1. 创建堆缓冲区容量10ByteBufferbufferByteBuffer.allocate(10);System.out.println(初始: posbuffer.position(), limitbuffer.limit());// 2. 写入数据buffer.put((byte)H);buffer.put((byte)i);buffer.put((byte)!);System.out.println(写入后: posbuffer.position());// 3// 3. 切换到读模式buffer.flip();System.out.println(flip后: posbuffer.position(), limitbuffer.limit());// pos0, limit3// 4. 读取数据while(buffer.hasRemaining()){System.out.print((char)buffer.get());}System.out.println();// 输出 Hi!// 5. rewind重新读buffer.rewind();System.out.println(rewind后 posbuffer.position());// 0// 6. clear清空状态准备重新写buffer.clear();System.out.println(clear后 posbuffer.position(), limitbuffer.limit());// pos0, limit10// 7. 直接缓冲区示例ByteBufferdirectBufByteBuffer.allocateDirect(1024);if(directBuf.isDirect()){System.out.println(这是直接缓冲区适合网络传输);}// 8. 字符串与 ByteBuffer 互转StringmsgHello NIO;ByteBufferbufByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8));// 读取时byte[]bytesnewbyte[buf.remaining()];buf.get(bytes);StringdecodednewString(bytes,StandardCharsets.UTF_8);System.out.println(decoded);}}四、避坑要点错误/误区后果正确做法写入后忘记flip()直接读取读不到数据position 在末尾写后读前必须flip()flip()多次调用limit被错误设置只在切换模式时调用一次直接缓冲区频繁分配释放性能反而下降复用缓冲区或使用池化技术使用get()前不判断hasRemaining()可能抛出BufferUnderflowException先判断或捕获异常五、面试高频考点Q1ByteBuffer的flip()方法做了什么将limit设为当前positionposition归零为从写模式切换到读模式做准备。Q2直接缓冲区的优缺点优点减少 JVM 堆和 native 堆之间的数据拷贝提高 I/O 性能适合大文件、网络。缺点分配和释放成本高不受 JVM 堆大小限制但受物理内存限制。Q3clear()和compact()的区别clear()重置position0, limitcapacity丢弃未读数据compact()将未读数据复制到缓冲区头部position移到未读数据后limitcapacity为写入留出空间。六、练习题代码填空完成如下操作写入字符串 “Java” 的字节然后读取并打印。简答什么时候使用直接缓冲区什么时候使用堆缓冲区动手用ByteBuffer和FileChannel实现文件拷贝使用transferTo或read/write。 你的学习进度当前第23篇 / 共44篇 ·第三阶段字符串、Buffer、枚举、类加载第21~25篇✅ 已完成第1~22篇 正在学第23篇⏳ 待学习第24~44篇 完整目录 学习指南 | 订阅本专栏不错过每一篇 本专栏每篇都包含避坑表 面试高频考点 练习题。每天30分钟100天拿offer下一篇文章预告《Java枚举类型 enum 用法》内容简介枚举的定义、构造器、成员变量和方法values()/valueOf()/ordinal()枚举单例模式。 学完这篇你将掌握枚举的全部用法并用枚举写出更安全的代码。《Java 100 天进阶之路 | 从入门到上岗就业》每天一篇建议收藏 关注一起100天拿offer 点击关注我更新后第一时间收到推送