ByteBuffer.slice()创建的是原缓冲区当前position到limit范围的只读视图,共享底层数组但独立维护状态,capacity固定为limit-position,position初始为0,适用于协议字段高效提取。

ByteBuffer.slice() 创建的是原缓冲区当前 position 到 limit 范围内的**只读视图(view)**,它不复制数据,而是共享底层字节数组,并独立维护自己的 position、limit、mark 和 capacity。这个特性让 slice 成为逻辑分段的高效手段。
slice 的核心行为:共享数据 + 独立状态
调用 slice() 后得到的新 ByteBuffer:
- 底层
array()(如果存在)与原缓冲区完全相同,修改 slice 中的内容会反映在原缓冲区中(反之亦然); - capacity 固定为原缓冲区当前
limit - position,且不可变; - position 初始为 0,limit 等于 capacity,mark 初始为 -1;
- 其 offset(即相对于原数组起始位置的偏移) = 原缓冲区的 position。
典型用途:协议解析中的字段提取
在网络或文件协议中,一个 byte[] 常包含多个连续字段(如头部长度+类型+负载)。用 slice 可避免拷贝,直接按逻辑切分:
- 先
buffer.getShort()读取 headerLen,再buffer.position(buffer.position() + headerLen)跳过头部; - 对 payload 区域调用
buffer.slice(),得到仅含有效负载的子缓冲区; - 后续可对该 slice 单独 flip/compact/put/get,不影响原 buffer 的其他区域。
注意事项:避免常见陷阱
使用 slice 时需注意几个关键点:
-
slice 不继承原 buffer 的 read-only 状态 —— 若原 buffer 是只读的,slice 默认也是只读的;但若原 buffer 可写,slice 仍可写(除非显式调用
asReadOnlyBuffer()); - slice 的 capacity 不随原 buffer 的 limit 改变而更新 —— 它在创建时就固定了大小;
- 调用
clear()或flip()在 slice 上,只影响 slice 自身的状态,不会改变原 buffer 的 position/limit; - 如果原 buffer 是 direct buffer,slice 也是 direct;如果是 heap buffer,slice 也共享同一 heap array。
对比 duplicate() 和 asReadOnlyBuffer()
三者都创建视图,但语义不同:
-
duplicate():共享全部状态(position、limit、mark、capacity),只是新引用; -
slice():共享数据 + 新的 position/limit(基于当前区间),capacity 缩小; -
asReadOnlyBuffer():返回只读副本,状态和容量完全一致,但禁止写操作。










