这篇文章源自一个需求的思考🤔。我们在日常开发可能会碰到类似这样的场景:
    image.png
    一个页面中有多种状态,我们常用的做法是定义N个变量来保存各个的状态,eg. x=是否允许向我提问、x=是否允许短信提醒我、x=是否允许电话提醒我、x=是否允许发起语音通话。这样做的结构清晰,也方便后续扩展。其实除了这种方式之外,还有另外一种方式:通过一个变量来标记多个状态,具体怎么做呢?
    我们先定义一个Number类型的正整数变量记做X,已知Number.MAX_SAFE_INTEGER最大值是9007199254740991,也就是2 - 1,把它转成二进制:
    image.png
    有没有发现,其实我们定义的X的转换成的二进制的每一位都是状态值(1-打开,0-关闭),最大可以表示53个状态值,足够我们用了。有了这个思路后,后面就好处理了。
    image.png
    比如,我们想实现允许向我提问允许电话提醒我,表示方式为:X= 0b0001 | 0b0010 = 0b0011 = 3,服务端只需要返回一个数字3,我们这里就知道哪些开关是开启的了 (判断方式:eg.X & 0010 != 0 既说明该位状态是1)。
    这种利用二进制位来解决一个变量处理多个状态的问题,我也是在安卓源码里学到,而且安卓源码里这一块的运用还是比较多,对应的状态值也有十几个,像下图这样的:
    image.png
    通过这样的操作,能很方便进行位的运算(AND/OR/XOR/NOT)。其实说到二进制的运用,我们接触到第一个示例,可能是在学校期间学习C语言时的一个示例:《交换两个变量数值》
    image.png
    通过异或操作,在不新增变量的前提下交换了两个变量的值了。

    还有一个比较经典的老鼠毒药问题,比较经典的一个答案也是利用二进制的思路解决的。
    有 1000 个一模一样的瓶子,其中有 999 瓶是普通的水,有一瓶是毒药。任何喝下毒药的生物都会在一星期死亡。现在,你只有 10 只小白鼠和一星期的时间,如何检验出哪个瓶子里有毒药?
    读完这个题后,想必大家心中都有了解题思路。10只小白鼠,相当于有10个二进制位,能最大标识210=1024种状态,足够标识1000个瓶子了。
    image.png_
    最后解题思路是:根据0-9编号小白鼠的死亡情况得到了一个二进制数,转换成十进制,就能得到是几号瓶的水有毒了。
    针对这类基于二进制位的运算,用起来并不是太方便,在各个语言类库里都能找到对应类库(三方或官方的)。记得Java里有个专门做这个的类:BitSet.java
    上面说了这么,总结的来说是是利用二进制的每位能够标示0-1两种状态。有关这方面的操作,有个更高级的名词:位图(Bitmap),关于Bitmap是什么,能做哪些事儿,我们就在放到后面的文章里介绍了。