flip()是Buffer从写到读的指针重置操作:将limit设为当前position、position归零、mark置-1,不改变数据和capacity,仅通过调整position与limit的相对关系重新定义可读区间。

flip 方法不是模式切换的“开关”,它只是重置两个指针:把当前写入终点设为读取边界,再把读取起点归零。Java NIO 中根本没有独立的“读模式”或“写模式”对象状态,所谓模式,完全由 position 和 limit 的相对关系决定。
flip 做了什么(纯指针操作)
调用 flip() 等价于执行三行字段赋值:
- limit = position —— 把“可读数据的末尾”定在刚写完的位置
- position = 0 —— 下一次 get() 从缓冲区开头开始读
- mark = -1 —— 失效标记位,避免 rewind() 误跳转
底层数组(无论是堆内数组还是堆外内存)一个字节都不动,不复制、不清空、不分配新空间。它只改 Buffer 对象内部的三个 int 字段。
为什么这就算“切换”了模式?
因为读写行为依赖指针逻辑:
立即学习“Java免费学习笔记(深入)”;
- 写时:put() 只允许在 [position, limit) 范围内写,初始 limit = capacity
- 读时:get() 只允许在 [position, limit) 范围内读,flip 后这个区间变成 [0, 原position)
同一个区间,写的时候是“可用写入空间”,读的时候就变成“有效数据范围”。flip 不改变数据,只重新解释这段内存的语义边界。
不调用 flip 会怎样?
假设写了 5 个字节,position=5,limit 仍为 capacity(比如 10):
- 直接 get() → 从索引 5 开始读,但有效数据只在 0~4 → 读到 0 或抛 BufferUnderflowException
- hasRemaining() 返回 true(因 5
flip 就是告诉 Buffer:“别再按 capacity 算了,我只认这前 5 个字节是有效的。”
和 clear/rewind 的本质区别
三者都设 position=0,但 limit 处理不同,导致语义完全不同:
- flip():limit = 原 position → “刚写完,现在要读这些”
- clear():limit = capacity → “已处理完,准备写全新的内容”
- rewind():limit 不变 → “还没读完,想再从头看一遍”
它们不是功能相似的“重置方法”,而是服务于不同业务意图的状态调整指令。


















