两个数交换位置:int a = 1;int b = 2;如何交换ab两个变量的值?
①使用第三个变量来接收
int c = 0;
c = a; // c 等于1
a = b; // a 等于2
b = c; // b 等于1
当然灵活运用,这种方式肯定是不推荐的啦!
②刷新一下你对小学数学的理解
a = a + b; // a 等于3
b = a - b; // b 等于1
a = a - b; // a 等于2
③既然是程序员,我们用程序员的方式来做一下,还可以深刻理解一下^
//如果m、n两个值不相同,则异或结果为1。如果m、n两个值相同,异或结果为0。
//1 的二进制 : 0000 0001
//2 的二进制 : 0000 0010
//3 的二进制 : 0000 0011
a = a ^ b; // a 等于 1 ^ 2 = 0000 0011 = 3
b = a ^ b; // b 等于 3 ^ 2 = 0000 0001 = 1
a = a ^ b; // a 等于 3 ^ 1 = 0000 0010 = 2
异或也叫半加运算,(相当于二进制个位相加,结果看个位)其运算法则相当于不带进位的二进制加法:二进制下用1表示真,0表示假,则异或的运算法则为:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),这些法则与加法是相同的,只是不带进位,所以异或常被认作不进位加法。
是不是很奇妙。下面看一个一样奇妙的与& 、 或 | 的操作。
- 我们经常会遇到需要存一组boolean值得时候,这些值有个特点,便是只有两种情况,要么true、要么false,或者说要么正确、要么错误,在或者说要么0,要么1。ok,就是这个01,也就是今天的主角,二进制。
逢二进一,借一当二
我们也可以把二进制想成一个盒子,一个容器,里面装的便是你要存储的boolean值。举个栗子,后台认证的时候,用户手机号是否认证,邮箱是否认证,是否实名认证,地址是否填了,紧急联系人是否填了,微信是否认证,QQ是否绑定,银行卡是否绑定……
那么这个二进制容器就可以来装这些数据了,1就是已经放进盒子里面了,0就是没放进盒子里面。
手机号 | 邮箱 | 身份证 | 地址 | 紧急联系人 | 微信 | 银行卡 | |
---|---|---|---|---|---|---|---|
1 | 0 | 1 | 0 | 1 | 0 | 1 | 1 |
- 下面讲解代码上怎么展现:
讲之前先说& | 的用法吧
二进制中
- 两个数都为1,&的值才为1,否则为0
即数学中的同时成立,条件才成立 - 两个数都为0,|的值才为0,否则为1
即数学中的任意一个成立,条件便成立
好,现在进入正题
int bankCard = 1 ;
int QQ = 1 << 1;
int weChat = 1 << 2;
int person = 1 << 3;
int idCard = 1 << 4;
int addr = 1 << 5;
int email = 1 << 6;
int phone = 1 << 7;
在将上面的这些值转换为二进制的数:
//不一定是8位的二进制数据,只是演示,节目效果
0000 0001:银行卡
0000 0010:QQ
0000 0100:微信
0000 1000:紧急联系人
0001 0000:地址
0010 0000:身份证
0100 0000:邮箱
1000 0000:手机号
那么转化为上面的格子的图,是不是就是这样。
手机号 | 邮箱 | 身份证 | 地址 | 紧急联系人 | 微信 | 银行卡 | |
---|---|---|---|---|---|---|---|
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
如果认证了手机号,就在手机号里面填1,没认证就是0,其他的也一样。
- 向格子插入数据的时候:
int state= 0;
state = state | phone ;
·····························解析·····························
//0000 0000 ——>state开始时候的二进制
//1000 0000 ——>phone的二进制
//1000 0000 ——>|(或)运算结果,state变成了1000 0000,从而实现存储
//实现了phone的存入,其他数据类似,
- 从格子查询数据的时候:
int state = 10;
phone = state & phone;
·····························解析·····························
//state为任意值,为了验证有绑定的,也有没绑定的,所以取个10。
//0000 1010 ——>state=10的二进制
//1000 0000 ——>phone二进制
//0000 0000 ——>&(与)结果为0,说明还没有绑定手机
---------------------------------------------------------------
QQ = state & QQ ;
·····························解析·····························
//0000 1010 ——>state=10的二进制
//0000 0010 ——>QQ二进制
//0000 0010 ——>&(与)结果为 1 << 1,即QQ的二进制,说明已经绑定了QQ
综上所述,只要判断state&<变量名>是否为0,即可得出是否绑定
这样可存可取,是不是比原来声明8个boolean类型的变量要好呢?在我们阅读源码的时候也经常会遇到这样的存取方式,了解便好!
另外,还有一种情况,就是已经绑定了手机号,但是需要取消绑定,这个时候使用&|就不能达到需求了。这个时候就需要上面讲过的^。
还用state=10来举例子,已知10里面存入了‘QQ’和‘紧急联系人’,看看怎么取消QQ的绑定。
int state = 10 ;
state = state ^ QQ ;
·····························解析·····························
//0000 1010 ——>state=10的二进制
//0000 0010 ——>QQ二进制
//0000 1000 ——>^(异或)结果为1<<3,表示state仅剩紧急联系人,成功取消QQ
至此,使用二进制来存储数据就完整结束了,有更好的想法,更多的见解,更妙的猜想,更深的疑惑……欢迎评论,我们讨论、互相学习。
上代码
public class BitStateUtils {
// 进行中
public static final int DOING_BITSTATE = 1;
// 成功
public static final int SUCCESS_BITSTATE = 1 << 1;
// 失败
public static final int FAILED_BITSTATE = 1 << 2;
public static void main(String[] args) {
// 数据库查出来的存储值
int a = 123;
// 是否有当前状态
boolean hasState = hasState(a, DOING_BITSTATE);
// 添加当前状态后的state
int addState = addState(a, DOING_BITSTATE);
// 删除当前状态后的state
int removeState = removeState(a, DOING_BITSTATE);
System.out.println(hasState);
System.out.println(addState);
System.out.println(removeState);
}
/**
* //0000 1010 ——>state=10的二进制
* //0000 0010 ——>1 << 1二进制
* //0000 0010 ——>&(与)结果为 1 << 1 不等于0
* @param states 当前状态值
* @param value 需要判断状态常量
* @return 是否存在
*/
public static boolean hasState(Integer states, int value) {
if(states == null){
return false;
}
return (states & value) != 0;
}
/**
* //0000 0000 ——>state开始时候的二进制
* //0000 0010 ——>1 << 1的二进制
* //0000 0010 ——>|(或)运算结果 包含 1 << 1
* @param states 当前状态值
* @param value 需要添加状态常量
* @return 新的状态值
*/
public static int addState(Integer states, int value) {
states = states == null ? 0 : states;
return (states | value);
}
/**
* //0000 1010 ——>state=10的二进制
* //0000 0010 ——>1 << 1二进制
* //0000 1000 ——>^(异或)结果已经取消了 1 << 1
* @param states 当前状态值
* @param value 需要删除状态常量
* @return 新的状态值
*/
public static int removeState(Integer states, int value) {
states = states == null ? 0 : states;
if (!hasState(states, value)) {
return states;
}
return states ^ value;
}
}