在做转换之前先要明确几个简单的概念。首先本文是以java为语言,以int为例子。 long数据类型在原理上是一致的。
1 int 在java中是32位, byte是8位。
2 原码,反码,补码简介
原码:就是二进制码,最高位为符号位,0表示正数,1表示负数,剩余部分表示真值。
反码:在原码的基础上,正数反码就是他本身,负数除符号位之外全部按位取反。
补码:正数的补码就是自己本身, 负数的补码是在自身反码的基础上加1.
3 看到这里又涉及到了一个按位与的操作, 所以我们要理解&(与), | (或), ^ (异或),~ (按位取反)
& :当2个都为1的时候为1, 其他都是0 。 1&1 = 1, 1&0 = 0, 0&0 = 0; 他的作用是清0
| : 当2个只要有一个为1,就是1. 1|0 = 1; 0|0 = 0, 1|1 = 1;
^: 相同为0, 不相同为1, 1^0 = 1, 1^1 = 0, 0^0 = 0; 他的作用是定位翻转。
~: 按位取反,0变为1, 1变为0;
之所以要明确原码,反码,补码,是因为java中变量都是以补码的形式保存的。
比如 整行30 他的原码是:0001 1110. 正数,所以反码,补码都是0001 1110.
对于负数:-7 ,他的原码是 1000 0111, 第一位1表示是此数是负数。他的反码是:1111 1000, 补码在反码的基础上加1, 所以它的补码是1111 1001, 所以他的二进制数就是1111 1001. 对于负数根据二进制求真值,就是再补码的基础上再求补码。 而之所以引入补码的原因是因为: 1 如果用源码,那么0000 0000 和1000 0000 貌似都0, +0 , 和- 0. 所以这造成了问题,第二个原因是因为cpu计算器只有加法没有减法, 减法需要用正数和负数相加得到。
如“-16+11”的运算:
11110000 + -16的补码
00001011 11的补码
————
11111011 - 5的补码
4 因为byte是8位,int是32位所以在转换过程中,肯定涉及到了移位, 在java中<< (左移), >>(带符号右移), >>>(无符号右移)
<< 左移,比如, a << b, a表示需要移位的整行, b表示向左移动的位数, 左移的规则是,右端(低位)补0, 丢去高位
比如 0000 0000 0000 0110, 左移2位就是0000 0000 0001 1000. 如果移动的位数大于32, 那么就需要取余, 比如移动34位,那么实际应该是 : 34%32 = 2, 左移2位。左移在不溢出的情况下移动一位就相当于乘2。
>>右移,比如 , a >>b, a表示需要变换的数值, b表示移动的位数,右移的一点要明确,符号位不变,左端(高位)补充的是符号位,比如 0000 0000 0000 1011, 右移2位是 1100 0000 0000 0010. 负数的移位高位补充的是1, 因为这个,所以变换的时候需要&0xFF.
>>>无符号右移,顾名思义是指移动的时候不考虑符号,右移的时候高位补0.
明确了以上概念,写代码反而简单了:
/**
* int到byte[] 由高位到低位
* @param i 需要转换为byte数组的整行值。
* @return byte数组
*/
public static byte[] intToByteArray(int i) {
byte[] result = new byte[4];
result[0] = (byte)((i >> 24) & 0xFF);
result[1] = (byte)((i >> 16) & 0xFF);
result[2] = (byte)((i >> 8) & 0xFF);
result[3] = (byte)(i & 0xFF);
return result;
}
/**
* byte[]转int
* @param bytes 需要转换成int的数组
* @return int值
*/
public static int byteArrayToInt(byte[] bytes) {
int value=0;
for(int i = 0; i < 4; i++) {
int shift= (3-i) * 8;
value +=(bytes[i] & 0xFF) << shift;
}
return value;
}