基础知识
整形(int)
4个字节,占32位,1111,1111,1111,1111,1111,1111,1111,1111。
整型int 其实不能说是去掉3个字节,只能说在读取数据的时候只读取了最低的一个字节里的数据而已,那另外的3个字节还在 ,只是没有读取里面的内容而已,因为高位都是0,可以不显示。int转换成4个byte的时候,byte[4] b=b[0][1][2][3]需要移位,从1个字节开始移位。
字节(byte)
1个字节,占8位,1111,1111。byte的数据范围:-128-127,255+符号位=256长度。
byte转换成int,需要左移(数据范围低->数据范围大,发生自动类型转换)。int转换成byte,需要右移。位移
左移
<<低位补0,相当于×2的n次方。右移
>>高位补0,相当于/2的n次方补码反码
Java的2进制采用的是补码形式。包括:2进制转10进制,10进制转2进制。
第1位表示符号位,符号位是负数情况,按补码进行存取。
负数都是按照补码形式表示。补码=反码+1。
反码=原码除了符号位之外,进行按位取反。正数
原码,反码,补码都相同负数
原码=源码,反码=除了第一个符号位为1,其他全部按位取反,补码=反码+1int在byte[]
byte[]图解
“一”表示一个字节,即 8位:一,一,一,一。- 下标0:从32位右移24位,
>>24,在下标3的位置,需要把高位清空为0,用&,即&0x0000ff;以此类推。 - 下标1:
>>16,0x00ff,0xff=f表示4位二进制数,f=1111。 - 下标2:
>>8,0xff。 - 下标3:不移动,也不需要清空0。
1
2
3[0] [1] [2] [3] 表示 index
一, 一, 一, 一
[0] [1] [2] [3]
1个int用byte表示[0][1][2][3],1个byte占8位,一个int占32位,一个int[]代表一个byte大小。1
2
3
4value%256 b[3]
value/256%256 b[2] //表示,除以256是b[3]的256,%是获取b[2]的值
value/65536%256 b[1]
value/16777216%256 b[0]----》256*256*256
int有正负数,所以要消除符号位(&256),负数的符号位补码影响。256=$2^8$ = 1111,1111,每位都可以表示:0,1;所以1111,1111 = $2^8$。1
2
3
4
5
6
7
8
9value%256 b[3] //取余是b[3]的值
value/256%256 b[2] //除以256是b[3]的256,是获取b[3]的值,%是获取b[2]的值
value/65536%256 b[1] //256*256,这里的256是,b[3],b[2]的2个256,扣除b[3],b[2]的2个256,b[1]的值是取余的获得
value/16777216%256 b[0] //256*256*256==[3],[2],[1]的256
或
value&255 b[3] //&255表示清除值是负数,高位是1,java2进制按照补码取值.0&1=0;低位8个11,高位24个0.
(value&255)>>8 b[2]
(value&255)>>16 b[1]
(value&255)>>24 b[0]
b[0][1][2][3]多维素组1
2
3
4
5b[0][1][2][3]
b[0]:256的3次方 11111111,11111111,11111111,11111111
b[1]:256的2次方 //[1],[2],[3]
b[2]:256的1次方 //[2],[3]
b[3]:256的0次方 //[3]
int->byte
例子1
转换成 byte[] b1
int a=270
因为byte占256长度,超出256长度,则溢出,向高位进1,a = 270 = b[1][14]
b每1维占256长度,超过进1位。1
2
3
4
5
6
7
8
9public static void main(String[] args) {
int a = 2;
byte[] b = new byte[4];
b[0] = (byte) (a >> 24); //第一个字节
b[1] = (byte) (a >> 16); //第二个字节
b[2] = (byte) (a >> 8); //第三个字节
b[3] = (byte) (a); //第四个字节
System.out.println(b[0] + "" + b[1] + "" + b[2] + "" + b[3]);
}
1 | 0002 |
例子2
(int类型)156转byte是-100。156=10011100最高位为符号位,而11100=28 故为-28,结果为10011100(此时,第一位符号位为1,为负),由于负数按补码存储,所以转换为byte之后的真值为反码=11100101,补码=11100100(进1位),然后加上-1(符号位是-1),即-100。
例子3
1 | public static void main(String[] args) { |
- 95+46=141
(00000000 00000000 00000000)10001101- 负数,按补码的方式存
10001101的补码11110010 - 64 +32+ 16 +2=(-)114 //补码的方式进行,负号还是要保留
- 符号位占一位,-114-1 = -115
byte->int
0xFF
将byte[]转化十六进制的字符串,注意这里b[i] & 0xFF将一个byte和0xFF进行了与运算,然后使用Integer.toHexString取得了十六进制字符串,可以看出b[i] & 0xFF运算后得出的仍然是个int,那么为何要和0xFF进行与运算呢?直接Integer.toHexString(b[i]);将byte强转为int不行吗?答案是不行的。 byte的大小为8bits,int的大小为32bits- Java的二进制采用的是补码形式(正数:源码,反码,补码相同。负数:源码。反码除了符号位,其余相反。补码是反码+1)
0xFF=1111,1111;因为前3个字节不读取,只是读取最后一个字节,所以可以看成1111,1111;但是实际上还是00000000,00000000,00000000,1111,1111。这样就可以消除因为负数符号位,补码的时候按位取反,高位是1的情况,&实际上是为了消除1。1
2
3
4
5
6
7
8
9
10
11public static String bytes2HexString(byte[] b) {
String ret = "";
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
ret += hex.toUpperCase();
}
return ret;
}
例子1
没有&2551
2
3
4
5
6public static void main(String[] args) {
byte b=-1;
int a=b;
String c=Integer.toBinaryString(a);
System.out.println(c);
}
1 | 11111111,11111111,11111111,1111,1111 |
有&2551
2
3
4
5
6public static void main(String[] args) {
byte b = -1;
int a = b & 255; //1
String c = Integer.toBinaryString(a);
System.out.println(c);
}
1 | 1111,1111 |
代码标注
255=0xff=1111,1111=0000,0000,0000,0000,1111,1111;通过&运算进行,前24位被清1。
Java中的一个byte,其范围是-128~127的,而Integer.toHexString的参数本来是int,如果不进行&0xff,那么当一个byte会转换成int时,对于负数,会做位扩展(因为负数是取补码,按位取反,&0xff是为了负数),举例来说,一个byte的-1(即0xff),会被转换成int的-1(即0xffffffff),那么转化出的结果就不是正确。而0xff默认是整形,所以,一个byte跟0xff相与会先将那个byte转化成整形运算(32位),这样,结果中的高的24个byte就总会被清1。
例子2
1 | public static void main(String[] args) { |
1 | 0002 |
&255(0x000000ff)
消除符号位,比如负数的情况,要按照补码取值,补码是反码+1。这里有可能b是负数,高位按照补码进行存取会是1111,1111...,所以要消除1。

