Java有4大类运算符:算术运算、位运算、关系运算和逻辑运算。
运算符的优先级
优先级 | 运算符 |
---|---|
1 | ( ) [ ] .(点运算符) |
2 | ! ++ -- ~ +(正) -(负) |
3 | * / % |
4 | + - |
5 | >> >>> << |
6 | < <= > >= |
7 | == != |
8 | & |
9 | ^ |
10 | | |
11 | && |
12 | || |
13 | ?: |
14 | = += -+ *= /= %= |
模运算符
Java中,模运算符不止可以用在对整数类型取模,还可以用在浮点类型(这点跟很多其他的编程语言不一样),如
int x = 9;
double y = 40.5;
System.out.println(y%x);
运行结果:
4.5
复合赋值运算符
复合赋值运算符:“+=”,“-=”,“*=”,“/=”,“%=”(两个运算符中间不要有空格)
对于,javatotal *= sum + 12;
等价于:total = total * (sum + 12);
有关“++”(“--”也适用)运算符的说明:
public class Hello {
public static void main(String[] args) {
int i = 10;
int k = i + ++i;
System.out.println(k);
i = 10;
int j = i++ + i;
System.out.println(j);
i = 10;
int m = i + i++;
System.out.println(m);
i = 10;
int n = ++i +i;
System.out.println(n);
}
}
运行结果:
21
21
20
22
- 首先声明,
当 i = 10 时,进行 “i++” 运算后, i 的值是 11,而“i++”这个表达式的值是10;
当 i = 10 时,进行 “++i” 运算后, i 的值是 11,而“++i”这个表达式的值也是11; - 优先级相同的四则运算,运算顺序是从左往右的。
对于int k = i + ++i;
,左边的 i 取值为 10,右边的 i 取值也为10,此时先计算 “++i” 的值(“++”,“--”为单目运算符,运算优先级比算数运算高),为11。所以 k 的值为 21。
对于int j = i++ + i;
,左边的 i 取值为 10,先进行 “i++” 的运算,此时 i = 11,“i++” 的值为10。所以 j 的值为 21。
对于int m = i + i++;
,左边的 i 取值为10,右边的 i 取值也为 10,而 “i++” 的值为 10,故 m 的值为 20。
对于int n = ++i +i;
,左边的 i 取值为 10,经过 “++i” 的计算表达式值为 11,i 的值为11,故 n 的值为 22。
运算符“++”前置等价于“+=1”。如,有int i = 1,则“++i” 与“i += 1”效果一样,表达式的值都为2。
int i = 1;
System.out.println(i+=1);
运算结果:
2
int i = 1;
System.out.println(++i);
运算结果:
2
int i = 1;
System.out.println(i++);
运算结果:
1
位运算符
Java定义的位运算(bitwise operators)直接对整数类型的位进行操作,这些整数类型包括long,int,short,char和 byte。
运算符 | 结果 |
---|---|
~ | 按位非(NOT)(一元运算) |
& | 按位与(AND) |
| | 按位或(OR) |
^ | 按位异或(XOR) |
>> | 右移 |
>>> | 右移,左边空出的位以0填充 |
<< | 左移 |
&= | 按位与赋值 |
|= | 按位或赋值 |
^= | 按位异或赋值 |
>>= | 右移赋值 |
>>>= | 右移赋值,左边空出的位以0填充 |
<<= | 左移赋值 |
Java使用大家知道的2的补码 (two's complement) 这种编码来表示负数,也就是通过将与其对应的正数的二进制代码取反(即将1变成0,将0变成1),然后对其结果加1。要对一个负数解码,首先对其所有的位取反,然后加1。
位逻辑运算符
按位非也叫做补,一元运算符NOT“~”是对其运算数的每一位取反。
按位与运算符“&”,如果两个运算数都是1,则结果为1。
按位或运算符“|”,任何一个运算数为1,则结果为1。
按位异或运算符“^”,只有在两个比较的位不同时其结果是 1。否则,结果是零。
按位异或运算符有一个有用的属性,如
00101010 42
^00001111 15
---------------
00100101 37
可以看到,通过按位异或,取出了低位的值。
左移运算符
左移运算符<<使指定值的所有位都左移规定的次数。它的通用格式如下所示:
value << num
每左移一个位,高阶位都被移出(并且丢弃),并用0填充右边。
在对byte和short类型的值进行移位运算时,由于Java会自动把这些类型扩大为 int型,而且,表达式的值也是int型 。对byte和short类型的值进行移位运算的结果是int型,而且如果左移不超过31位,原来对应各位的值也不会丢弃。但是,如果你对一个负的byte或者short类型的值进行移位运算,它被扩大为int型后,它的符号也被扩展。这样,整数值结果的高位就会被1填充。因此,为了得到正确的结果,你就要舍弃得到结果的高位。这样做的最简单办法是将结果转换为byte型。
public class test {
public static void main(String[] args) {
byte a = 64, b;
int i;
byte c = -64, d;
int j;
j = c << 2;
i = a << 2;
d = (byte)(c << 2);
b = (byte) (a << 2);
System.out.println("Original value of a: " + a);
System.out.println("i and b: " + i + " " + b);
System.out.println("Original value of c: " + c);
System.out.println("i and b: " + j + " " + d);
}
}
该程序产生的输出下所示:
Original value of a: 64
i and b: 256 0
Original value of a: -64
i and b: -256 0
每次左移都可以使原来的操作数翻倍,所以这个办法可以用来进行快速的2的乘法。但是,如果将1移进高阶位(31或63位),那么该值将变为负值。
class MultByTwo {
public static void main(String args[]) {
int i;
int num = 0xFFFFFFE;
for(i=0; i<4; i++) {
num = num << 1;
System.out.println(num);
}
}
}
该程序的输出如下所示:
536870908
1073741816
2147483632
-32
右移运算符
右移运算符>>使指定值的所有位都右移规定的次数。它的通用格式如下所示:
value >> num
这里,num指定要移位值value移动的位数。
将值每右移一次,就相当于将该值除以2并且舍弃了余数。
所以,如果想利用这个特点将一个整数进行快速的2的除法,需要确保你不会将该数原有的任何一位移出。
右移时,被移走的最高位(最左边的位)由原来最高位的数字补充。如果要移走的值为负数,每一次右移都在左边补1,如果要移走的值为正数,每一次右移都在左边补0,这叫做符号位扩展(保留符号位)(sign extension),在进行右移操作时用来保持负数的符号。
由于符号位扩展(保留符号位)每次都会在高位补1,因此-1右移的结果总是–1。(-1的二进制补码是全1)
若不希望在右移时保留符号,用按位与可以实现。如,要进行运算的是byte型的数,则将它的值转换为用十六进制表示。注意右移后的值与0x0f进行按位与运算,这样可以舍弃任何的符号位扩展。
无符号右移
当处理像素值或图形时,就常常不希望进行符号位扩展。
Java的无符号右移运算符>>>,总是在左边补0。
由于无符号右移运算符>>>总是把short和byte型的数据扩大为int型,所以只是对32位和64位的值有意义。如,
byte b = (byte) 0xf1;
byte d = (byte) (b >>> 4);
运算结果d的值为0xff。
关系运算符
在C/C++中,这些类型的语句是很常见的:
int done;
// ...
if(!done) ... // Valid in C/C++
if(done) ... // but not in Java
而在Java中,这些语句必须写成下面这样:
if(done == 0)) ... // This is Java-style.
if(done != 0) ...
因为在C/C++中,任何非0的值为真,而0值是假。但是,Java中真值、假值跟数字没有关系。
所有的关系运算符的优先级比算数运算的低,但是比赋值运算的高。
判断是否相等的 == 和 != 的优先级比其他的低,而连续的关系运算是从左到右进行的。
布尔逻辑运算符
运算符 | 含义 |
---|---|
& | 逻辑与 |
| | 逻辑或 |
^ | 异或 |
|| | 短路或 |
&& | 短路与 |
! | 逻辑反 |
&= | 逻辑与赋值(赋值的简写形式) |
|= | 逻辑或赋值(赋值的简写形式) |
^= | 异或赋值(赋值的简写形式) |
== | 相等 |
!= | 不相等 |
?: | 三元运算符(IF-THEN-ELSE) |
两个boolean类型的数据可以做 == 和 != 的比较,但是不可以做 > ,>= , < , < =运算。boolean类型的不可以和整型或浮点型的数据作比较。
短路逻辑运算符
对于 && 运算,如果左边表达式的值为false,就不在计算右边表达式的值,直接得出为false的结论;
对于 || 运算,如果左边的表达式值为true,就不在计算右边表达式的值,直接得出true的结论。
短路逻辑运算符的应用,如,
if (denom != 0 && num / denom > 10)
防止被0除错误。
赋值运算符
赋值运算符允许你对一连串变量赋值。如,
int x,y,z;
x = y = z = 100;
括号运算符
圆括号(不管是不是多余的)不会降低你程序的运行速度。因此,添加圆括号可以减少含糊不清,不会对你的程序产生消极影响。
结合关系
例:
int result = 2;
result = (result = result * 2) * 6 * (result = 3 + result);
此处 result 的运算结果是168。即,先计算左边括号里的表达式,再计算右边括号里的表达式。
真正自己编程的时候,这个表达式应该被拆成若干个表达式,然后以明显的正确的顺序来进行计算。如,
int result = 2;
int temp;
int tempTwo;
result = result * 2;
temp = result;
tempTwo = result +3;
result = temp * 6 * tempTwo;
网友评论