ByteBuffer字节数组转short结果不符预期,Bits类实现疑问
字节数组转short时得到-1而非预期65535的问题分析与解决
问题重现
在Java 8环境下,我编写了一段将字节数组转换为short类型的代码:
byte arr[] = {-1,-1}; int value = ByteBuffer.wrap(arr).order(ByteOrder.LITTLE_ENDIAN).getShort();
运行后得到的value为-1,但预期结果应该是无符号16位整数对应的65535。
原因分析
深入查看JDK的转换逻辑后,发现java.nio.Bits类中的makeShort方法负责完成实际的转换工作,其实现如下:
private static short makeShort(byte var0, byte var1) { return (short)(var0 << 8 | var1 & 255); }
问题出在var0的处理上:Java的byte是有符号类型,当var0为-1时,其二进制表示为11111111。在执行左移操作前,byte会被自动提升为int类型,此时符号扩展会将其变为0xFFFFFFFF,左移8位后得到0xFFFFFF00。与var1 & 255(-1 & 255结果为0xFF)执行或运算后,最终结果为0xFFFFFFFF,强转为short时仅保留低16位的0xFFFF,对应有符号short的-1。
解决方案
你提出的修改makeShort方法的思路是正确的,通过var0 & 0xFF将有符号byte转换为无符号的int,避免符号扩展:
private static short makeShort(byte var0, byte var1) { return (short)((var0 & 0xFF) << 8 | var1 & 255); }
不过需要注意的是,Java的short本身就是有符号类型,即使修改后强转得到的short值依然是-1(对应二进制0xFFFF)。如果要直接获取无符号的65535,更简便的方式是使用Java 8为ByteBuffer新增的getUnsignedShort()方法,该方法直接返回无符号的int结果:
byte arr[] = {-1,-1}; int value = ByteBuffer.wrap(arr).order(ByteOrder.LITTLE_ENDIAN).getUnsignedShort();
运行这段代码就能得到预期的65535。
内容的提问来源于stack exchange,提问作者Abhinav Singh
相关产品推荐
相关产品推荐

