asreadonlybuffer()创建共享底层数组的只读视图,限制写操作但不复制数据;新缓冲区与原缓冲区共享内存,独立维护position等状态,isreadonly()返回true,任何写操作抛readonlybufferexception。

用 asReadOnlyBuffer() 创建只读视图,核心是让调用方只能读、不能改底层数据,同时避免复制开销。它不生成新数组,而是共享原缓冲区的 backing array,仅限制写操作。
只读视图的本质是共享+隔离
调用 asReadOnlyBuffer() 后,新缓冲区与原缓冲区:
- 指向同一块内存(比如
heapByteBuffer.array()) - 拥有各自独立的
position、limit、mark和capacity - 新缓冲区的
isReadOnly()返回 true - 任何
put()、compact()、flip()(含写语义的操作)都会立即抛出ReadOnlyBufferException
典型安全使用场景
适用于需要对外暴露数据但禁止篡改的场合:
- 网络框架中将接收缓冲区转为只读后传给业务处理器,防止误写导致后续解析错乱
- 多线程环境下,主线程构造好数据后分发只读视图给工作线程,规避同步或意外修改
- 封装工具类时,返回只读缓冲区作为“不可变快照”,如
getDataView()方法
关键注意事项
只读视图不是绝对保险,需配合使用习惯:
- 原缓冲区仍可被修改 → 修改后,只读视图读到的内容也会变(这是共享内存的特性,不是缺陷)
- 只读缓冲区无法转回可写状态 → 没有
asWritableBuffer()这样的逆向方法 - 若原缓冲区已是只读,
asReadOnlyBuffer()行为等价于duplicate(),返回另一个只读副本 - 对只读缓冲区调用
array()可能成功(取决于是否基于堆),但直接修改该数组仍会破坏数据一致性,不推荐
简单验证示例
以下代码可快速验证行为:
ByteBuffer bb = ByteBuffer.allocate(4).put(new byte[]{1,2,3,4}).flip();
ByteBuffer ro = bb.asReadOnlyBuffer();
System.out.println(ro.get(0)); // 输出 1,读取正常
ro.put((byte)9); // 抛出 ReadOnlyBufferException
bb.put(0, (byte)99); // 原缓冲区仍可写
System.out.println(ro.get(0)); // 输出 99,只读视图内容已变










