关键在于根据缓冲区当前数据状态选择操作:写完待读用flip,读完待写用clear,读一半需保留未读数据并追加时用compact。

熟练切换 ByteBuffer 的 flip、clear 和 compact,关键不在死记方法名,而在于理解当前缓冲区处于什么数据状态,以及你接下来要做什么操作。
写完就全读:用 flip 切换到读模式
刚写入一批数据(比如从 Channel 读进 buffer,或手动 put 字符串),position 指向末尾,limit 还在 capacity。这时不能直接 get——因为 limit 太大,会越界或读到脏数据。
调用 flip() 就是告诉 buffer:“写完了,现在开始读”。它把 limit 设为当前 position,再把 position 归零。这样后续 get() 就能安全读出所有已写入内容。
- 适用场景:一次写满、准备完整读取(如解析完整报文头)
- 注意:flip 后不能再 put,否则会覆盖未读数据或抛 ReadOnlyBufferException
读完就清场:用 clear 重置为写模式
已经把 buffer 里的数据全部读完(hasRemaining() 返回 false),且下一轮要写全新数据,这时调用 clear() 最合适。
clear 不动内存数据,只重设指针:position = 0,limit = capacity,mark = -1。逻辑上“清空”,物理上旧数据还在,但后续 put 会自然覆盖。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 适用场景:HTTP 响应处理完、日志写入完毕、等待下一条新请求
- 常见误区:在还有未读数据时调用 clear —— 会导致数据丢失
读一半还要追加:用 compact 保留未读部分
比如网络收包时,只读了前 20 字节(发现是个不完整的包),但 buffer 剩余空间还有 80 字节,你想继续等后续数据填满再解析。这时不能 flip(已读过)、不能 clear(会丢掉那 20 字节之后的未读内容)。
compact() 把 position 到 limit 之间的未读数据(即还没 get 的字节)拷贝到 buffer 起始处,然后设置 position = 未读字节数,limit = capacity。相当于“腾出前面空间,把尾巴挪到开头”。
- 适用场景:TCP 粘包处理、分片接收、协议解析中需累积数据
- 效果示例:buffer 容量 10,写了 7 字节,flip 后读了 3,剩余 4 字节未读 → compact 后,这 4 字节移到索引 0~3,position=4,可继续 put 新数据
怎么选?看三件事:是否读完、是否还要旧数据、下步是读还是写
不必背口诀,每次操作前快速问自己:
- 刚写完,下一步要读?→ flip
- 刚读完,下一步要写全新数据?→ clear
- 读了一半,还想接着写新数据,且要保留没读完的老数据?→ compact
真正卡住人的,从来不是方法不会调,而是没意识到 buffer 此刻“肚子里还剩什么”。多打印 capacity/limit/position,比查文档更快定位问题。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










