,,^,~,,写出高效艺术的代码

简介:

大家在阅读源码的时候经常会看到一些比如下面这样特别难理解的代码。

cancelEvent.setAction(MotionEvent.ACTION_CANCEL |(motionEvent.getActionIndex()<< MotionEvent.ACTION_POINTER_INDEX_SHIFT));order = ((order) >> (INDEX_OFFSET -1) + 1) << INDEX_OFFSET;类似与这种“高大上”的代码在各类大神写的代码或源码中随处可见。

这种代码是什么意思?为什么要这么写?这么写的好处?怎么才能写出这样的代码?我们就带着这些疑问来看下面的文章吧。

逻辑运算符:

逻辑运算符主要用来计算真假值(boolean),通常用在条件判断语句中。

逻辑运算是我们平时用的最多的,主要有&&,||,&,|。相信大家都熟悉,所以这里只简单介绍一下&&和&的区别:

对于&&和||,如果左边判断通过就不会判断右边了。而&和|则是两边等式都需要计算。

(所以这里有个技巧,如果不需要两边都判断的话则用&&或||并且可以把需要用时多的计算条件放在右边,用时少的放在左边)

位运算符:

位运算符主要对二进制数(int)做操作。

包括:与(&),或(|),非(~),异或(^),左移(<<),右移(>>>),正负右移(>>)。

与(&):两边都是1(true),结果才为1(true),否则结果为0(false)

例:1 & 2 = 0001 & 0010 = 0000 = 0

或(|):两边有一个为1(true),结果就为1(true)。两边都是0(false),结果才是0(false)

例:1 | 3 = 0001 | 0011 = 0011 = 3

非(~):如果位为0(false),结果是1(true),如果位为1(true),结果是0(false)

例:~ 4 = ~0100 = 1011 = 11

异或(^):两个操作数的位中,相同则为0(false),不同则为1(true)

例:1 ^ 4 = 0001 ^ 0100 = 0101 = 5

左移(<<):向左移动运算符右边指定的位数,并且在低位补零。或相当于将(左边的值)乘上2 的(右边值) 次方

例:1 << 4 = 0001向左移动4位 = 10000 = 16 或者 = 1 * 2^4 = 16

右移(>>>):向右移动运算符右边指定的位数,并且在高位补零。或相当于将(左边的值)除以2 的(右边值) 次方

例:4 >>> 2 = 0100向右移动2位 = 0001 = 1 或者 = 4 / 2^2 = 1

正负右移 (>>):向右移动运算符右边指定的位数。如果是正数,在高位补零。如果是负数,则符号位为1,最高位是补0或是补1 取决于编译系统的规定.

例:

4 >> 2 =0100向右移动2位后高位补0 = 0001 = 1

-4 >> 2 = -0100向右移动2位后高位补1 = -0100 向右移动两位后高位补1 = -0001 = -1

首先我们要有一个概念,使用二进制的目的就是要用1和0当做标志位,通常把1当成true,0当成false。这样就可以在一个变量中携带多个标志位信息。

这里举个例子,大家看后就明白了。

需求是这样的,有4个权限判断,分别是A,B,C,D。我们要根据不同的权限组合来进行不同的操作。

public static final int PASS_BY_A = 1;//0001public static final int PASS_BY_B = 2;//0010public static final int PASS_BY_C = 4;//0100public static final int PASS_BY_D = 8;//1000public static final int PASS_BY_ABCD = PASS_BY_A|PASS_BY_B|PASS_BY_C|PASS_BY_D; //1111/** * @param args */public static void main(String[] args) {boolean isA = false;boolean isB = false;boolean isC = false;boolean isD = false;int isPass = -1;// 获取权限然后为各个权限变量赋值,这里忽略initParameter();// 使用传统的boolean去做判断,是否满足ABCD四个权限if (isA & isB & isC & isD) {}// 使用二进制做判断,是否满足ABCD四个权限if ((isPass & PASS_BY_ABCD) == 0) {}}通过对比可以看出,使用二进制做判断,变量的使用量,效率还有代码简洁程度大大提高。这也是在各种各样的源码里二进制和位运算被经常使用的原因。

位运算使用技巧总结:

最后我总结出了一些我在使用二进制和位运算时发现的一些小技巧。

a | b:合并ab中的1。

例1:a为1100(12),b为0001(1),a|b=1101(13)。

例2:a=0001(1)。这时候想让a=1111(15)。最简单的做法就是找个b=1110(14)。a | = b (a = a | b)

a & b:判断a中的1和b中的1是否完全不同(例1)。合并ab中的0(例2)。1与任何数与运算都得任何数(例3)

例1:a为1010,b为0101; a & b = 0000(0)。如果 a & b = 0,这就说明a中的1和b中的1完全不同。

例2:a为1110,b为1001; a & b = 1000(8)。合并ab中的0,或理解为使用0来替换掉原有的位

例3:a为1001000,b为11110000; a & b = 10010000 = a。所以经常有代码中使用在需要的位数标记为1,不需要的位数标记为0,作为遮罩(MASK),来得到遮罩范围内的值。

a ^ b:找出ab中的不同/相同(1为不同,0为相同)。

例1:比如a为1100(12),b为0111(7)。a ^ b = 1011(11)

a << b 和 a >>> b:左移和右移通常都是为二进制赋值,和改变值

例1:a=0001(1)。a<<1=0010(2), a<<2=0100(4), a<<3=1000(8),配合for循环可以很快的为二进制赋值。

例2:a=1100(12), INDEX_OFFSET = 0001(1)。 a >>>=INDEX_OFFSET = 0110(6), a >>>=INDEX_OFFSET = 0011(3)。

而且大家在程序中做2倍数乘除法的时候最好是使用左移和右移操作,这样效率会提高很多。

最后列出4*4的二级制数集合

3=0011

标注颜色的2组为比较常用的。可以的话大家可以背下来几组,免得现用现算,这样编程效率就会大大增加。

一般在做程序的时候4*4个标志位基本够用了。如果不够可以5*5,6*6等等。使用标志位判断越多的时候二进制的优势就越明显。

总结&感受:

生气是拿别人做错的事来惩罚自己

,,^,~,,写出高效艺术的代码

相关文章:

你感兴趣的文章:

标签云: