bytebuffer.putshort() 是按当前字节序将 short 拆为两个字节写入 position 处并递增 position,需配合 flip() 读取、注意字节序一致性及缓冲区状态,适用于协议封包等底层精确控制场景。

ByteBuffer.putShort() 这类方法不是“随便写写就能用”的通用存值工具,而是面向字节序列精确控制的底层操作。要真正精准存取数值型变量,关键不在调用方法本身,而在于理解它背后的字节序、位置偏移、缓冲区状态和类型映射逻辑。
一、putShort 的本质:两个字节的有序写入
putShort(short value) 是相对写入(relative put),它:
- 按当前
byteOrder(默认为BIG_ENDIAN)将short(16位有符号整数)拆成两个字节; - 写入到
position所指位置; - 写完后自动将
position += 2; - 若
position > limit - 2,抛出BufferOverflowException; - 若缓冲区只读,抛出
ReadOnlyBufferException。
ByteBuffer buf = ByteBuffer.allocate(10); buf.putShort((short) 0x1234); // position=0 → 写入 [0x12, 0x34],之后 position=2
⚠️ 注意:
0x1234在BIG_ENDIAN下是高位在前;若设为LITTLE_ENDIAN,则实际写入[0x34, 0x12]。
二、避免踩坑的三个实操要点
手动管理 position 和 limit
不要依赖“写完就刚好读”的直觉。写入后需调用flip()才能切换为读模式;若继续写,记得clear()或compact()。-
绝对写入更可控(适合结构化布局)
用putShort(int index, short value)可跳过 position 状态,直接往指定下标写(例如构造协议头时固定偏移写长度字段):buf.putShort(4, (short) payloadLen); // 第5、6字节存负载长度,不扰动 position
类型与字节严格对应,不自动转换
putShort()只接受short;传int会编译报错,传(short) 65536实际存的是0(溢出截断)。
同理,getShort()读出的永远是short,即使你本意是无符号 16 位(此时需用getChar()或手动 & 0xFFFF 转成int)。
三、配合 getShort 实现端到端精准读写
写入和读取必须使用一致的 byteOrder 和位置逻辑,否则数值错乱:
ByteBuffer buf = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN); buf.putShort((short) 0x5678).putInt(0x12345678); buf.flip(); // 准备读 short s = buf.getShort(); // → 0x5678(小端:内存中是 0x78 0x56) int i = buf.getInt(); // → 0x12345678(小端:内存中是 0x78 0x56 0x34 0x12)
- 若写用
BIG_ENDIAN,读用LITTLE_ENDIAN,getShort()会把高低字节倒过来解释,结果完全错误; - 若写完没
flip()就直接getShort(),可能读到未初始化区域或越界。
四、何时该用 putShort,何时不该用?
- ✅ 适合:网络协议封包、文件二进制格式、JNI 数据桥接、需要与 C struct 对齐的场景;
- ❌ 不适合:临时缓存、高频增删的集合操作、业务逻辑层的数据传递(这时用
List<integer></integer>或 DTO 更安全清晰); - ? 替代思路:如需频繁读写混合类型,可封装
DataBuffer工具类统一管理 order/position/边界检查,避免裸调putShort出错。
不复杂但容易忽略。











