clear()用于完全丢弃旧数据并重置缓冲区,position=0、limit=capacity;compact()用于保留未读数据并前移,position设为未读长度、limit=capacity,适用于粘包等需续写场景。

调用 clear() 或 compact() 是重置 NIO 缓冲区以准备复写数据的两种常用方式,但它们适用场景不同,行为也明显区别。选错方法可能导致数据丢失或逻辑错误。
clear():适合完全丢弃旧数据、从头写入
当缓冲区中的数据已处理完毕(如已写入通道),且你打算完全清空内容、重新开始写入
- 将
position设为 0 - 将
limit设为capacity -
mark被清除(设为 -1) - 不修改底层数组内容,只是重置读写指针
示例:从 SocketChannel 读取完一批数据并处理后,准备下一次 read:
buffer.clear(); // 恢复为可写状态,position=0, limit=capacitycompact():适合保留未读数据、追加新内容
当缓冲区中还有部分数据未被消费(例如 position ,即还有“剩余字节”没读完),但你想继续往后面写入新数据时,用 compact() 更安全:
- 把
[position, limit)区间的数据移到缓冲区开头(即未读数据前移) - 更新
position为原未读数据长度(即移动后的末尾位置) - 更新
limit为capacity -
mark被清除
典型场景:使用 ByteBuffer 做网络粘包处理,一次 read 没读满一个完整消息,下次需在剩余空间继续追加:
关键区别速查
- clear():假设“旧数据已无用”,直接重置指针;适合写入前的初始化
- compact():假设“旧数据还有残留”,先整理再续写;适合读取中途需要继续 fill 的情况
- 两者都不清空数组内容,也不改变 capacity
- 如果误在有未读数据时调用 clear(),会导致那些数据被后续 write 覆盖而丢失
配合 flip() 理解更清晰
回忆标准读写循环:
→ read() 后调用 flip()(为读做准备)
→ get() 或 write() 后,若要复用缓冲区:
✓ 全部数据已处理完 → clear()
✓ 还剩部分未读 → compact()










