1. 按位与& :两位全位1,结果才为1;
0&0=0; 0&1=0 ; 1&1=1
如:51 &5 =0011 0011 & 0000 0101=0000 0001 = 1
作用:清零、取一个数中指定位(即被与数0000)
2. 按位或| :只要有一个为1,结果就为1 ;
3. 异或^ :相同为0,不同为1 ;
0 ^ 0 =0 ; 0 ^1 = 1 ; 1 ^ 1=0;
作用:使特定位翻转(^ 1111 即翻转)
4. 取反运算 ~ :按位取反, 0变成1 ,1变成 0;
5. <<左移运算 :将一个运算对象的各二进制位全部左移若干位(左边的丢弃,右边的补0)
6. >>右移运算:将一个数各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。
7. >>>无符号右移:各个位向右移指定的位数,左边空出的位用0来填充,移出的右边位丢弃。
以下都是对负数而言,正数的原码、补码、反码都是其本身(原码)。
8. 原码:一个正数按照绝对值大小转换成的二进制数称为原码;
9. 反码:将二进制数按位取反。(符号位不取反)
10. 补码:反码+1;
11. 引入原码反码 和补码的目的就是为了解决减法问题,因为计算机CPU的运算器中只有加法器,要把减法转化成加法来计算。
如“-16+11”的运算:
11110000 + -16的补码
00001011 11的补码
————
11111011 - 5的补码
有了以上知识,下面做int和byte的互相转换:
public static byte[] intToByte(int a){
byte bt[]=new byte[4];
bt[0]=(byte)((a>>0*8)&0xff);
bt[1]=(byte)((a>>1*8)&0xff);
bt[2]=(byte)((a>>2*8)&0xff);
bt[3]=(byte)((a>>3*8)&0xff);
return bt;
}
public static int byteToInt(byte[] a){
System.out.println((int)a[0]); //这里输出的是-49
System.out.println((int)(a[0]&0xff));//这里输出是207
int rs0=(int)((a[0]&0xff)<<0*8);
int rs1=(int)((a[1]&0xff)<<1*8);
int rs2=(int)((a[2]&0xff)<<2*8);
int rs3=(int)((a[3]&0xff)<<3*8);
int result=rs0+rs1+rs2+rs3;
return result;
}
发现一个奇怪的现象, 直接输出(int)a[0]结果是-49,而(int)(a[0]&0xff)理论上不变,但是输出的结果却是207;
原来,java的int是4个字节32位的,在控制台进行输出的时候,jvm把11001111之前进行了补全,补为11111111 11111111 11111111 11001111,显然这是-49的补码,输出结果是-49;而如果进行了a[0]&0xff ,补全后则变成00000000 00000000 00000000 11001111,此时结果变成了207,这时进行运算结果才是正确的。
java中,转换时int输出时 若byte符号位是0,如01001000,则进行int补0处理--》00000000 00000000 00000000 01001000;
若byte符号位是1,如11001000,则进行补1处理-->1111111 11111111 11111111 11001000
Ps: &0xff的作用就是把其他位置0,这八位不变;
一些实用的函数:Integer.toBinaryString(8100);可以输出二进制码;
String s="abc"; byte[] bt = s.getBytes();可以得到字符串的二进制码// s.getByte("utf-8")参数也可以指定编码方式!
for(byte b:bt){
System.out.println(Integer.toBinaryString(b));//输出二进制码
}
如果通过字节序列变成string,可以通过String s=new String(bt,"asci"); 形式