hasremaining() 返回 position
hasRemaining() 是 NIO Buffer 中判断当前缓冲区是否还有未读/未写数据的最直接方法,但它不是单纯“看是否空”,而是依赖于 position 和 limit 的相对关系。
hasRemaining 的本质逻辑
它等价于:position 。 这意味着:只要当前位置还没到达界限,就返回 true —— 无论你是在读模式还是写模式,也不管 buffer 是刚分配、刚 flip 过、还是部分消费过。
- 写入后未 flip:position 在数据末尾,limit 仍是 capacity → hasRemaining() 为 true(但此时不能读,因为没 flip)
- flip 后:limit 被设为原 position,position 归零 → 可安全读,hasRemaining() 表示“还有字节可读”
- 读了一部分:position 前移,只要还没到 limit,hasRemaining() 仍为 true
- 读完或写满:position == limit → 返回 false
典型读场景中的正确用法
从 Channel 读取数据到 ByteBuffer 时,需配合 read() 的返回值和 hasRemaining() 判断是否一次读完:
- 先 clear() 或 compact()(视情况),确保 buffer 处于可写状态
- 调用 channel.read(buffer),返回实际读到的字节数(可能为 0 或 -1)
- 若返回值 > 0,再调用 buffer.flip() 进入读模式
- 之后用 while (buffer.hasRemaining()) { buffer.get() } 安全遍历所有已读数据
典型写场景中的常见误区
向 Channel 写出数据前,必须确保 buffer 处于读模式(即已 flip),否则 hasRemaining() 虽可能返回 true,但读不到有效数据:
- 错误:写入数据后直接 write(buffer),未 flip → position 在末尾,limit 仍是 capacity → hasRemaining() 为 true,但 write() 实际发送 0 字节
- 正确:put 数据 → flip() → while (channel.write(buffer) > 0 && buffer.hasRemaining()) {}(注意 write 可能未写完,需循环)
- 更稳妥写法:flip 后检查 hasRemaining(),再进入 write 循环,每次 write 后若 buffer 仍有剩余,继续写
注意 hasRemaining 不等于 isEmpty 或 isFull
Buffer 没有 isEmpty() 方法,hasRemaining() 不能替代它。例如:
- 一个刚分配、未 put 任何数据的 buffer:position=0, limit=capacity → hasRemaining() == true(但它逻辑上是空的)
- 一个 put 了 5 字节后 compact() 的 buffer:position=0, limit=5 → hasRemaining() == true(表示可读 5 字节)
- 要判断“是否真有数据可读”,必须保证 buffer 已 flip;否则 hasRemaining() 只反映 position/limit 关系,不反映业务语义












