capacity是底层数组长度且固定不变,position是下一次读/写的起始索引,limit是当前操作的边界;三者须满足0≤position≤limit≤capacity,flip()将limit设为当前position再置position为0以切换至读模式。

ByteBuffer 的 capacity、position、limit 到底谁管什么
这三个变量不是“概念”,是真实可读写的整数字段,直接决定你能读/写多少、从哪开始、到哪截止。搞错顺序或手动乱设,BufferUnderflowException 或 BufferOverflowException 立刻报给你看。
简单说:capacity 是底层数组长度,固定不变;position 是下一次读/写的游标;limit 是当前操作的边界(读时不能超 limit,写时不能超 limit)。它们之间必须满足:0 ≤ position ≤ limit ≤ capacity。
-
put()写入后自动递增position,但不会动limit -
get()读取后也自动递增position - 调用
flip()是关键转折点:它把limit设为当前position,再把position归零 —— 这是为“从头读刚写完的数据”做的准备 - 别手贱直接
position = 0或limit = capacity,除非你真清楚自己在绕过状态机
flip() 不是“重置”,而是切换读写模式的开关
很多人以为 flip() 就是“清空 buffer 重新来”,其实它只做两件事:limit = position,然后 position = 0。它不擦数据,也不改 capacity,更不会把已写内容变“未写”。
典型误用场景:写完一段数据后没 flip() 就直接 get(),结果读到的是 position 后面的脏数据(可能是 0,也可能是上次残留),甚至抛 BufferUnderflowException。
- 写模式 → 读模式:必须
flip() - 读模式 → 写模式:用
clear()(重置 position=0, limit=capacity)或compact()(把未读完的数据移到开头,再调整 position/limit) -
rewind()只是position = 0,limit 不变 —— 适合“重读一遍当前已写内容”,但不能用于写前准备
allocate() 和 wrap() 创建的 ByteBuffer,状态初始值不同
ByteBuffer.allocate(1024) 返回的是“写模式就绪”状态:position=0, limit=capacity=1024;而 ByteBuffer.wrap(new byte[]{1,2,3}) 返回的是“读模式就绪”状态:position=0, limit=3, capacity=3。这个差异直接影响你第一句该调 put 还是 get。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
尤其注意 wrap() 后如果想往里写,得先 clear() 或手动 set limit;否则 put() 会因 position ≥ limit 直接炸。
- 用
allocate():默认可立即put() - 用
wrap(byte[]):默认可立即get(),想写得先处理 limit - 用
wrap(byte[], offset, length):limit = offset + length,不是整个数组长度
直接内存(DirectBuffer)和堆内 Buffer 的翻转逻辑完全一致
是不是 direct 不影响 capacity/position/limit 的行为,只影响内存分配位置和 GC 行为。翻转图解里的箭头、数字关系,在 ByteBuffer.allocateDirect(1024) 上一模一样。
但要注意:direct buffer 的创建和回收成本更高,别为了“看起来快”就滥用;而且它的 array() 方法会抛 UnsupportedOperationException —— 如果你后面还打算用 get(byte[]) 拷贝,得提前确认是不是 heap buffer。
- 判断是否 direct:
buffer.isDirect() - 获取底层字节数组(仅 heap buffer):
buffer.array(),别在 direct 上调 - 跨 JVM 进程共享或 native 调用才真正需要 direct;普通网络 IO,heap buffer +
channel.write(buffer)效果不差
最常被忽略的一点:翻转不是目的,是读写角色切换的副产品。盯着三个变量数值看不如盯住你此刻要干的事——是在填数据,还是在掏数据?选对方法比记住图解重要得多。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










