位运算大家平时用的比较少,但是当你看jdk源码时发现会有很多位运算。我们知道,计算机最基本的操作单元是字节(byte),一个字节由8个位(bit)组成,一个位只能存储一个0或1,其实也就是高低电平。无论多么复杂的逻辑最终体现在计算机最底层都只是对01的存储和运算。java中我们使用算数操作符操作数据 1+2 实际上 jvm最终也会编译为位运算进行计算,所以有一些比较复杂的运算我们可以考虑通过位运算来实现,提高效率,当然在后面的文章我也会在权限系统中使用位运算实现权限校验存储。
位运算用来操作整数基本数据类型中的单个"比特"(bit),即二进制位。整数类型包括 long,int,short,char 和 byte。位运算在java中分为位逻辑运算符和位移运算符两类,再开始讲解位运算之前先和大家在复习一下10进制于2进制的转化过程。
10进制转2进制:
方法为:十进制数除2取余法,即十进制数除2,余数为权位上的数,得到的商值继续除2,依此步骤继续向下运算直到商为0为止。
2进制转10进制
方法为:把二进制数按权展开、相加即得十进制数。
嗯,上述是百度经验分享过来的。好接下来我们开始详细介绍每类位运算:
.位逻辑运算:
位逻辑运算符包含 4 个:&(与)、|(或)、~(非)和 ^(异或)。
&(与):
位相同为1,不同位为0,看下面的demo:
public static void main(String[] args){
int a=129;
int b=128;
System.out.println("a 和b 与的结果是:"+(a&b));
}
运行结果a 和b 与的结果是:128,可能有的同学觉得奇怪怎么会128了呢,别急我们分析一下这个程序:上述说道位运算都是操作二进制位,那么我们先把 a = 129 转化为2进制10000001(同学们自己跟着算一下),b=128转化为2进制10000000,根据与逻辑运算符的运算规律,只有两个位都是1结果才是1,对比后二进制结果=10000000,换算成10进制也就是128咯!
或(|):
两个位只要有一个1则为1,否则为0
public static void main(String[] args)
{
int a=129;
int b=128;
System.out.println("a 和b 或的结果是:"+(a|b));
}
运行结果 a 和b 或的结果是:129 。好我们接着来分析:
a 的值是129,转换成二进制就是10000001,而b 的值是128,转换成二进制就是10000000,根据或运算符的运算规律,只有两个位有一个是1,结果才是1,可以知道结果就是10000001,即129。
非(~):
如果值为 0 结果为1 为1结果为0(二进制比如 ~10000 = 01111),得到反码后再+1得到补码
public static void main(String[] args) {
int a = 10;
System.out.println("a 非的结果是:"+(~a));
}
运行结果 a 非的结果是:-11。10的2进制是 00000000 00001010 然后我们取反码 11111111 11110101 在+1得到补码 1000000000001011,用十进制数表示即为 -11。(二进制最高位是1则为负数,0则为正数)
异或(^)
两个操作数中同位数值相同结果为0,不同值结果为1
public static void main(String[] args)
{
int a=15;
int b=2;
System.out.println("a 与 b 异或的结果是:"+(a^b));
}
运行结果a 与 b 异或的结果是:13
分析上面的程序段:a 的值是15,转换成二进制为1111,而b 的值是2,转换成二进制为0010,根据异或的运算规律,可以得出其结果为1101 即13。
.位移运算符
位移运算符包含三种 <<(按位左移运算符), >>(按位右移运算符) >>>(按位右移补零操作符)
左移运算符<<
左移运算符<<是将左边的对象向左移动右边指定的位数,并且在低位补0。其实向左移动n位就相当于乘以2的n次方
public static void main(String[] args)
{
int a=2;
int b=2;
System.out.println("a 移位的结果是:"+(a<<b));
}
运行结果a 移位的结果是:8,分析上面的程序段:
首先从本质上来分析,2 的二进制是00000010,它向左移动2 位,就变成了00001000,即8。如果从另一个角度来分析,它向左移动2 位,其实就是乘上2 的2 次方,结果还是8。
右移运算符>>
右移是将运算符左边的运算对象,向右移动运算符右边指定的位数。如果是正数,在高位补零,如果是负数,则在高位补1,先看下面一个简单的例子。
public static void main(String[] args)
{
int a=16;
int c=-16;
int b=2;
int d=2;
System.out.println("a 的移位结果:"+(a>>b));
System.out.println("c 的移位结果:"+(c>>d));
}
运行结果 a 的移位结果:4c 的移位结果:-4
分析上面的程序段:
a 的值是16,转换成二进制是00010000,让它右移两位成00000100 即4。
c 的值是-16,转换成二进制是11101111,让它右移一位成11111011 即-4。
右移补零运算符>>>
右移补零运算符用符号“>>>”表示,是将运算符左边的对象向右移动运算符右边指定的位数,并且在高位补0,其实右移n 位,就相当于除上2 的n 次方。
public static void main(String[] args)
{
int a=16;
int b=2;
System.out.println("a 移位的结果是:"+(a>>>b));
}
运行结果 a 移位的结果是:4
分析上面的程序段:从本质上来分析,16 的二进制是00010000,它向右移动2 位,就变成了00000100,即4。如果从另一个角度来分析,它向右移动2 位,其实就是除以2 的2 次方,结果还是4。
好了今天的分享就到这里,下期我们将分享一个大型的权限管理系统使用spring security,包含单点登录,角色权限数据表设计,思路图等,大家多多关注我,可以进群一起讨论(978219630)