Java ByteBuffer在for循环中调用mark和reset是否必要?
在for循环中对ByteBuffer调用mark和reset是否有必要?
先看你给出的示例代码:
public static void writeToBuffer(final List<ByteBuffer> attachments, final ByteBuffer buffer) { for (ByteBuffer buf : attachments) { buf.mark(); // copy content of buf to buffer buf.reset(); } }
这个操作有没有必要,得看两个核心点:你的复制逻辑会不会修改buf的position/limit,以及复制完成后这个buf是否还会被后续代码使用。
情况1:有必要的场景
如果你的复制代码是类似buffer.put(buf)这种标准JDK方法——它会把buf中从当前position到limit的字节全部写入目标buffer,同时会把buf的position移动到limit的位置(相当于“消费”了这个buf的内容)。这时候如果后续代码还要用到这个buf的原始状态(比如还要读取它的内容,或者其他操作依赖它原来的position),那mark()和reset()就非常必要:
mark()会记录下循环开始时buf的position位置reset()会把position恢复到mark的位置,让buf回到初始状态,不影响后续使用
情况2:完全多余的场景
如果满足以下任意一个条件,这两个调用就是纯粹的性能浪费:
- 你的复制逻辑不会修改
buf的position/limit(比如手动遍历字节数组,或者使用不改变原buf状态的自定义复制方法) - 复制完成后这个
buf就不再被任何代码使用了(相当于用完就扔)
更优雅的替代方案
其实还有比mark/reset更稳妥的方式——如果你想避免修改原buf的状态,完全可以用duplicate()或者asReadOnlyBuffer()创建一个缓冲区副本,操作副本而不影响原buf:
public static void writeToBuffer(final List<ByteBuffer> attachments, final ByteBuffer buffer) { for (ByteBuffer buf : attachments) { // 创建只读副本,操作它不会改变原buf的position/limit ByteBuffer tempBuf = buf.asReadOnlyBuffer(); // copy content of tempBuf to buffer } }
这种方式更清晰,也不用担心忘记reset或者mark被覆盖的问题(毕竟ByteBuffer的mark是单个的,如果中间有其他操作修改了mark,reset就会出问题)。
内容的提问来源于stack exchange,提问作者niepan
相关产品推荐
相关产品推荐

