1. 概述
本文将探讨在Java中将字节数组(byte[]
)与数值类型(int
、long
、float
、double
)相互转换的多种方法。字节是计算机存储和处理的基本单位,而Java中的基本类型则是操作多字节的便捷方式。因此,字节数组与基本类型之间存在天然的转换关系。
由于short
和char
仅占2字节,转换相对简单,本文将重点讨论int
、long
、float
和double
类型的转换。
2. 使用位移运算符
位移运算符是实现字节数组与数值类型转换最直接的方式。
2.1 字节数组转int和long
将字节数组转换为int
时,使用左移运算符(<<
):
int value = 0;
for (byte b : bytes) {
value = (value << 8) + (b & 0xFF);
}
注意:字节数组长度应≤4(
int
占4字节),否则会导致溢出。
验证转换正确性:
byte[] INT_BYTE_ARRAY = new byte[] {
(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE
};
int INT_VALUE = 0xCAFEBABE;
int value = convertByteArrayToIntUsingShiftOperator(INT_BYTE_ARRAY);
assertEquals(INT_VALUE, value);
转换为long
时只需修改两处:
value
类型改为long
- 字节数组长度≤8
2.2 int和long转字节数组
将int
转换为字节数组时,使用右移运算符(>>
或>>>
):
byte[] bytes = new byte[Integer.BYTES];
int length = bytes.length;
for (int i = 0; i < length; i++) {
bytes[length - i - 1] = (byte) (value & 0xFF);
value >>= 8; // 或使用无符号右移 value >>>= 8
}
说明:此处
>>
和>>>
效果相同,因为只保留原字节内容。
验证转换:
byte[] bytes = convertIntToByteArrayUsingShiftOperator(INT_VALUE);
assertArrayEquals(INT_BYTE_ARRAY, bytes);
转换为long
时只需:
- 将
Integer.BYTES
改为Long.BYTES
- 确保
value
类型为long
2.3 字节数组转float和double
转换字节数组为float
需分两步:
- 先转为
int
- 通过
Float.intBitsToFloat()
解释位模式// 字节数组转int int intValue = 0; for (byte b : bytes) { intValue = (intValue << 8) + (b & 0xFF); } // int转float float value = Float.intBitsToFloat(intValue);
验证转换:
byte[] FLOAT_BYTE_ARRAY = new byte[] {
(byte) 0x40, (byte) 0x48, (byte) 0xF5, (byte) 0xC3
};
float FLOAT_VALUE = 3.14F;
float value = convertByteArrayToFloatUsingShiftOperator(FLOAT_BYTE_ARRAY);
assertEquals(Float.floatToIntBits(FLOAT_VALUE), Float.floatToIntBits(value));
提示:转
double
时,使用long
作为中间类型和Double.longBitsToDouble()
方法。
2.4 float和double转字节数组
将float
转为字节数组:
// float转int
int intValue = Float.floatToIntBits(value);
// int转字节数组
byte[] bytes = new byte[Float.BYTES];
int length = bytes.length;
for (int i = 0; i < length; i++) {
bytes[length - i - 1] = (byte) (intValue & 0xFF);
intValue >>= 8;
}
验证转换:
byte[] bytes = convertFloatToByteArrayUsingShiftOperator(FLOAT_VALUE);
assertArrayEquals(FLOAT_BYTE_ARRAY, bytes);
类比:转
double
时,使用Double.doubleToLongBits()
和long
类型。
3. 使用ByteBuffer
java.nio.ByteBuffer
提供了统一的转换方式,简洁且优雅。
3.1 字节数组与数值类型互转
字节数组转int
:
ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);
buffer.put(bytes);
buffer.rewind(); // 重置position到0
int value = buffer.getInt();
int
转字节数组:
ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);
buffer.putInt(value);
buffer.rewind();
byte[] bytes = buffer.array();
通用模式:
- 分配指定大小的
ByteBuffer
- 放入原始数据(
put()
或putInt()
等) - 重置position(
rewind()
) - 获取目标数据(
getInt()
或array()
)
优势:支持所有数值类型(
long
/float
/double
),只需修改类型相关常量(如Long.BYTES
)。
3.2 复用现有字节数组
使用ByteBuffer.wrap()
避免创建新数组:
float value = ByteBuffer.wrap(bytes).getFloat();
踩坑点:确保字节数组长度≥目标类型大小(如
Float.BYTES
),否则抛出BufferUnderflowException
。
4. 使用BigInteger
java.math.BigInteger
主要用于大数运算,虽能实现转换,但略显笨重。
4.1 字节数组转int和long
字节数组转int
:
int value = new BigInteger(bytes).intValue();
转long
:
long value = new BigInteger(bytes).longValue();
注意:使用
intValueExact()
/longValueExact()
会在溢出时抛出ArithmeticException
。
反向转换:
byte[] bytes = BigInteger.valueOf(value).toByteArray();
问题:
toByteArray()
返回最小字节数,可能不是4或8字节。
4.2 字节数组转float和double
需借助中间类型转换:
// 字节数组转float
int intValue = new BigInteger(bytes).intValue();
float value = Float.intBitsToFloat(intValue);
// float转字节数组
int intValue = Float.floatToIntBits(value);
byte[] bytes = BigInteger.valueOf(intValue).toByteArray();
类比:转
double
时使用long
和Double.longBitsToDouble()
。
5. 使用Guava
Guava的com.google.common.primitives
包提供了便捷方法。
5.1 字节数组转int和long
字节数组转int
:
int value = Ints.fromByteArray(bytes);
int
转字节数组:
byte[] bytes = Ints.toByteArray(value);
转long
:
long value = Longs.fromByteArray(bytes);
byte[] bytes = Longs.toByteArray(value);
实现原理:底层仍使用位移运算符。
5.2 字节数组转float和double
Floats
和Doubles
类未提供直接方法,需借助中间类型:
// 字节数组转float
int intValue = Ints.fromByteArray(bytes);
float value = Float.intBitsToFloat(intValue);
// float转字节数组
int intValue = Float.floatToIntBits(value);
byte[] bytes = Ints.toByteArray(intValue);
省略:
double
转换同理,使用Longs
和Double
方法。
6. 使用Commons Lang
Apache Commons Lang默认使用小端序(little-endian),需额外处理字节序。
6.1 字节数组转int和long
字节数组转int
:
byte[] copyBytes = Arrays.copyOf(bytes, bytes.length); // 避免修改原数组
ArrayUtils.reverse(copyBytes); // 转为小端序
int value = Conversion.byteArrayToInt(copyBytes, 0, 0, 0, copyBytes.length);
int
转字节数组:
byte[] bytes = new byte[Integer.BYTES];
Conversion.intToByteArray(value, 0, bytes, 0, bytes.length);
ArrayUtils.reverse(bytes); // 转回大端序
说明:
long
转换使用byteArrayToLong()
和longToByteArray()
。
6.2 字节数组转float和double
无直接方法,需通过中间类型转换:
// 字节数组转float
byte[] copyBytes = Arrays.copyOf(bytes, bytes.length);
ArrayUtils.reverse(copyBytes);
int intValue = Conversion.byteArrayToInt(copyBytes, 0, 0, 0, copyBytes.length);
float value = Float.intBitsToFloat(intValue);
// float转字节数组
int intValue = Float.floatToIntBits(value);
byte[] bytes = new byte[Float.BYTES];
Conversion.intToByteArray(intValue, 0, bytes, 0, bytes.length);
ArrayUtils.reverse(bytes);
7. 总结
本文介绍了Java中字节数组与数值类型转换的多种方法:
- 位移运算符:最基础高效,但需手动处理字节序
- ByteBuffer:官方推荐,代码简洁优雅
- BigInteger:适合大数场景,常规转换略显笨重
- Guava:API友好,底层仍用位移运算
- Commons Lang:需注意字节序问题,代码稍显繁琐
建议:优先使用
ByteBuffer
,兼顾性能与可读性;若项目已集成Guava,可考虑其工具类。