本文共 3260 字,大约阅读时间需要 10 分钟。
Java提供了丰富的运算符,可以将之分为四种:算术运算符、位运算符、关系运算符、逻辑运算符
算术运算符的操作对象必须是数值类型,不能为boolean类型使用算术运算符,但是可以为char类型使用算术运算符。因为在Java中,char类型在本质上是int的子集。
运算符 | 含义 |
---|---|
+ | 加法(也是一元加号) |
- | 减法(也是一元减号) |
* | 乘法 |
/ | 除法 |
% | 求模 |
++ | 自增 |
- - | 自减 |
+= | 加并赋值 |
-= | 减并赋值 |
*= | 乘并赋值 |
/= | 除并赋值 |
%= | 求模并赋值 |
Java定义了几个位运算符,可用于整数类型——long,int,short,char和byte。
运算符 | 含义 |
---|---|
~ | 按位一元取反 |
& | 按位与 |
| | 按位或 |
^ | 按位异或 |
>> | 右移 |
>>> | 右移零填充 |
<< | 左移 |
&= | 按位与并赋值 |
|= | 按位或并赋值 |
^= | 按位异或并赋值 |
>>= | 右移并赋值 |
>>>= | 右移零填充并赋值 |
<<= | 左移并赋值 |
在Java中,所有整数类型都由宽度可变的二进制数字表示,除char类型外都是有符号整数,这意味着它们即可表示正数,也可以表示负数。
Java中使用“2的补码”进行编码,即负数的表示方法为:首先反转数值中的所有位(1变为0,0变为1),然后再将结果加1。例如,-42的表示方法为:通过反转42中的所有位(00101010),得到11010101,然后再加1,得到11010110,即-42。 为了解码负数,首先反转所有位,然后加1。例如,反转-42(11010110),得到00101001,即41,再加一则得到42。位逻辑运算符包括&、|、^和~。
运算规则如下表所示A | B | A|B | A&B | A^B | ~A |
---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 1 |
1 | 0 | 1 | 0 | 1 | 0 |
0 | 1 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 | 0 |
左移运算符“<<”可以将数值中的所有位向左移动指定的次数,格式为:
value << num
num指定了将value中的值向左移动的次数,对于高阶位,每次左移都被移出并丢失,右边的位用0补充。这意味着左移int类型操作数时,如果某些位一旦超出31位,那么这些位将丢失。如果操作数是long类型,那么超出位63的位会丢失。
当左移byte和short型数据时,Java的自动类型提升会导致意外的结果。当对表达式进行求值时,byte和short型数值会被提升为int类型,且表达式的结果也是int型。 这意味着对byte和short型数值进行左移操作的结果为int型,若移动的位数不超出位31,则移动的位不会丢失。此外,当将负的byte和short型数值提升为int型时,会进行符号扩展,因此高阶位将使用1填充。 例如,如果左移byte型数值,会先将该数值提升为int型,然后左移。这意味着如果想要的结果是移位后的byte型数值,就必须丢弃结果的前三个字节,可以通过将结果强制转换为byte类型来完成位数截取。 举个例子:public static void main(String[] args) { public static void main(String[] args) { //0011 1100 byte a = 60; // a首先被提升为int类型,即(0000 0000 0000 0000 0000 0000 0011 1100) // 左移两位,结果为(0000 0000 0000 0000 0000 0000 1111 0000),即240 int i = a << 2; // 先左移两位,结果为(0000 0000 0000 0000 0000 0011 1100 0000) // 舍弃前三个字节,得到(1100 0000),即-64 byte b = (byte) (i << 2); System.out.println("i等于:" + i); System.out.println("b等于:" + b); } }
输出结果是:
i等于:240b等于:-64
因为每次左移都相当于将原始值乘2,所以可以将之作为乘法的搞笑替代方法。但是如果将二进制1移进高阶位,结果将会变成负数。
右移的规则与左移类似,实例代码如下:
public static void main(String[] args) { //0011 1100 byte a = 60; // a首先被提升为int类型,即(0000 0000 0000 0000 0000 0000 0011 1100) // 右移两位,结果为(0000 0000 0000 0000 0000 0000 0000 1111),即15 int i = a >> 2; // 先右移两位,结果为(0000 0000 0000 0000 0000 0000 0000 0011) // 舍弃前三个字节,得到(0000 0011),即3 byte b = (byte) (i >> 2); System.out.println("i等于:" + i); System.out.println("b等于:" + b); }
i等于:15b等于:3
每次右移一位,相当于将该值除以2,并舍弃所有余数。可以利用这一特性实现高效的除法操作。
当进行右移操作时,右移后的顶部(最左边)位使用右移前顶部为使用的值填充,这称为符号扩展。当对负数进行右移操作时,该特性可以保留负数的符号。
public static void main(String[] args) { byte a=(byte) 0b11111000; System.out.println("a等于:"+a); int b=a>>1; System.out.println("b等于:"+b); }
a等于:-8b等于:-4
每次移位时,“>>”运算符自动使用原来的内容填充高阶位,这个特性可以保持数值的正负性。但是,有时候对那些非数值的内容进行移位操作,并不关心高阶位初始值是多少,只希望用0来填充高阶位,这就是无符号右移。
为了完成无符号右移,需要使用Java的无符号右移运算符“>>>”,该运算符总是将0移进高阶位。public static void main(String[] args) { //二进制表示(11111111 11111111 11111111 11111111) int a=-1; System.out.println(a); //右移二十四位(00000000 00000000 00000000 11111111) a=a>>>24; //输出结果是 255 System.out.println(a); }
关系运算符用于判定一个操作数与另一个操作数之间的关系。
运算符 | 结果 |
---|---|
== | 等于 |
!= | 不等于 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
关系运算符用于判定一个操作数与另一个操作数之间的关系。
运算符 | 结果 |
---|---|
& | 逻辑与 |
| | 逻辑或 |
^ | 逻辑异或 |
|| | 短路或 |
&& | 短路与 |
! | 逻辑一元非 |
&= | 逻辑与并赋值 |
|= | 逻辑或并赋值 |
^= | 逻辑异或并赋值 |
== | 等于 |
!= | 不等于 |
?: | 三元运算符 |
转载地址:http://mzvra.baihongyu.com/