单目运算符、双目运算符、三目运算符
单目 双目 三目 -----> 参与运算的数字个数
运算优先级
百度百科: JAVA运算符优先级
看个例子
public static void main(String[] args) { int a = 10, b = 6; System.out.println("改变之前的数:a=" + a + ",b=" + b); a -= b++; System.out.println("改变之后的数:a=" + a + ",b=" + b); }
因为b++运算中先执行++,再返回后置++运算表达式(b++)的返回值(6)给-=运算符。 在这个程序中a-=b++等于a=a-b++=10-6,所以a=4。
i++ 和 ++i
1、首先,单独拿出来说++i和i++,意思都是一样的,就是i=i+1。
2、如果当做运算符来说,就是a=i++或者a=++i这样的形式。情况就不一样了。
先说a=i++,这个运算的意思是先把i的值赋予a,然后在执行i=i+1;
而a=++i,这个的意思是先执行i=i+1,然后在把i的值赋予a;
举个例子来说,如果一开始i=4。
那么执行a=i++这条语句之后,a=4,i=5;
那么执行a=++i这条语句之后,i=5,a=5;
同理,i–和--i的用法也是一样的。
位运算符
位操作只能用于整形数据,对float和double类型进行位操作会被编译器报错。
按位与运算【&】
双目运算符,参与运算的数以补码方式出现。
作用:参与运算的两数各对应的二进位相与
结果:只有对应的两个二进位均为1时,结果位才为1 ,否则为0。
7 5 转换为二进制 7 -- 00000111 5 -- 00000101 7&5 00000111 00000101 -------------- 00000101 -----> 7&5 = 5
按位或运算【|】
双目运算符,参与运算的数以补码方式出现。
作用:参与运算的两数各对应的二进位相或
结果:只要对应的二个二进位有一个为1时,结果位就为1。
7 5 转换为二进制 7 -- 00000111 5 -- 00000101 7|5 00000111 00000101 -------------- 00000111 -----> 7|5 = 7
按位异或运算【^】
双目运算符,参与运算的数以补码方式出现。
作用:参与运算的两数各对应的二进位相异或
结果:当两对应的二进位相异时,结果为1。
7 5 转换为二进制 7 -- 00000111 5 -- 00000101 7^5 00000111 00000101 -------------- 00000010 -----> 7^5 = 2
按位取反运算【~】
单目运算符。
作用:对参与运算的数的各二进位按位求反 ,通俗点说 1 变 0 , 0 变 1
1001的求反运算为: ~(1001) 结果为: 011
左移运算
左移运算符“<<”是双目运算符
作用:把“<<”左边的运算数的各二进位全部左移若干位,由“<<”右边的数指定移动的位数,高位丢弃,低位补0。
结果:左移n位就是乘以2的n次方
举个例子
例一:
a<<4 指把a的各二进位向左移动4位。如a=00000011(十进制3),左移4位后为00110000(十进制48)
a=00000011 ---> 十进制 3 a << 4 -----> 3 << 4 ----> 3的二进制左移4位 00000011 | | -->二进位向左移动4位 | 00110000 -----> 转换为 十进制 48 , 就是 3 * 2^4 = 3 * 16 = 48 故: 左移n位就是乘以2的n次方
例二
右移运算
右移运算符“>>”是双目运算符
作用:把“>>”左边的运算数的各二进位全部右移若干位,“>>”右边的数指定移动的位数。。
结果:右移n位就是除以2的n次方
例如:设 a=15,a>>2 表示把00001111右移为00000011(十进制3)
a=00001111 ---> 十进制 15 a >> 2 -----> 15 >> 2 ----> 15的二进制右移2位 00001111 | | -->二进制右移2位 , 把最后的2个11挤掉了,剩下的补0 | 00000011 -----> 转换为 十进制 3 , 就是 15 / 2^2 = 15 / 4= 3 故: 右移n位就是除以2的n次方
二进制间的移位比十进制间的计算效率高很多. x>>1;//相当于x/=2 x<<1;//相当于x*=2 x>>2;//相当于x/=4 x<<2;//相当于x*=4 x>>3;//相当于x/=8 x<<3;//相当于x*=8
应用
int型变量是奇数还是偶数?
public static void main(String[] args) { //判断int型变量是奇数还是偶数 /** * 分析 * 十进制 二进制 * 3 -----> 011 * 4 -----> 100 * 5 -----> 101 * 6 -----> 110 * * 奇数的最后一位 1 * 偶数的最后一位 0 * * & 两个二进位均为1时,结果位才为1 ,否则为0 * | 两个二进位有一个为1时,结果位就为1 * * 所以 & 合适 * * 1的二进制 也是 1 * * 3 & 1 ----> 011 & 001 ---> 001 ----> 对应十进制 1 * 4 & 1 ----> 100 & 001 ---> 000 ----> 对应十进制 0 * || * || * || * || * * 3&1 = 1 ---> 奇数 * 4&1 = 0 ---> 偶数 * * 所以 * a&1 = 1 奇数 * a&1 = 0 偶数 * */ for (int i = 0; i < 10 ; i++) { if ((i&1) == 1){ System.out.println(i + " 奇数"); }else{ System.out.println(i + " 偶数"); } } }
除数为2的n次方时,使用位操作(&运算)代替求余操作
当b为2的n次方时 , a % b = a & (b-1) (b=2^n)
/** * 位运算比十进制的运算要高效, * * 在某些情况下,当b为2的n次方时,有如下替换公式: * a % b = a & (b-1) (b=2^n) * * 即:a % 2^n = a & (2^n-1) * * * a = 12 , b = 2^3 = 8 * * 12 % 8 取余操作 = 4 * * 12 ------ 1100 * 8 ------ 1000 * 7 ------ 0111 * * 12 & 7 ---- 1100 * 0111 * -------- * 0100 ---------->十进制 4 */ System.out.println(12 % 8); System.out.println(12&7);
看下JDK1.7 HashMap的实现 也是这样操作的。
int 类型的 整数 a 、b 交换位置
/** * int 类型的 整数 a 、b * a 和 b 交换: * 常规思路 引入临时变量temp * * int temp = a ; a 赋值给临时变量 temp * a = b ; b赋值给a * b = temp; temp 赋值给b * * 异或^ 当两对应的二进位相异时,结果为1 * * a = 8 -------> 1000 * b = 9 -------> 1001 * * a ^= b; --> a = a^b --> a = 1000 ^ 1001 --> a = 0001 --> a = 1 * b ^= a; --> b = b^a --> b = 1001 ^ 0001 --> b = 1000 --> b = 8 * a ^= b; --> a = a^b --> a = 0001 ^ 1000 --> b = 1001 --> a = 9 * * */ int a = 8, b = 9 ; System.out.println("before switch【 a:" + a + " b:" + b + "】" ); if (a != b) { a^=b; b^=a; a^=b; } System.out.println("after switch 【 a:" + a + " b:" + b + "】" );