基础知识
整形(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[] b
1
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
没有&255
1
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 |
有&255
1
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。