Java的表达式和运算符
一、算术运算符
运算符 |
+ |
- |
* |
/ |
% |
说明 |
加 |
减 |
乘 |
除 |
取模(余数) |
例子 |
1+2 |
5-3 |
20*5 |
6/4 |
30%9 |
结果 |
3 |
2 |
100 |
1 |
3 |
和我们小学学得算术运算一样,不过这里要注意,整数的除法如果结果有小数,那么会自动的截断小数部分,例如以下这个例子:
1 2 3 4 |
|
其结果是1,不会带有小数部分,也就是整数运算后的到的结果也是整数,不会自动变成浮点数。
上面所具的例子都是表示二元运算符,也就是说有两个运算参数,其中“+”和“-”两个符也可以表示一元运算符,分别表示正数和负数这些运算符也可以组合成为一个复杂的运算式子,如下面这个例子:
1 2 3 |
|
运算的优先级和我们平时的数学算法一样,基本按照从左到右的计算,其中+和-具有相同的优先级,它们的优先级比*,/和%的运算低,但是*,/和%的运算优先级别又比一元运算符的+和-要低。与我们的数学算式一样,算术表达式也支持使用小括号更改计算的优先级,如下面这个例子:
1 2 3 |
|
上面示例会先计算小括号的x+y和a-b两个式子,然后在按照先先乘除后加减,从左到右的计算顺序。有关优先级的详细讲解我们在后面的章节中讲解。
二、赋值运算符
运算符 |
= |
+= |
-= |
*= |
/= |
++ |
-- |
说明 |
赋值 |
加等于 |
减等于 |
乘等于 |
除等于 |
自增1 |
自减1 |
例子 |
x=10 |
x+=y; |
y-=5; |
y*=z-3; |
z/=3; |
y++; |
x-- |
等价于 |
x=x+y; |
y=y-5; |
y=y*z-3; |
z=z/3; |
y=y+1; |
x=x-1; |
在程序中“=”的意义与我们平时的数学计算的式子不同,他表示赋值的意思,就是把赋值表达式中右边的计算结果赋值左边的变量中。如下面这里例子都是赋值运算:
1 2 |
|
在赋值运算时,经常会出现左边的变量重复出现在赋值表达式的右边,如:
1 2 |
|
赋值运算符的计算顺序都是从右边开始计算,也就是会先计算a+200的值,然后才会赋值给a,所以上面的例子会先取得a变量的值100,然后再加上200,最后把300的结果赋值给a变量,这时候a变量的值就是300。
由于像上面这样的运算在程序中常常会出现,为了提高编译的效率和书写代码的简易,java提供了一些相应的运算符号如:
+= -= *= /= %= >>= <<= &= ^= |=
有些运算符,我们在后面的章节中才会介绍,这些自操作赋值运算符是一种对编码简化的写法。有时运算比较复杂是为保证编码的可读性也可不用这种缩写的语法。像上面的列子:
1 |
|
等价于以下形式:
1 |
|
归纳一下也就是,如果expr1和expr2分别代码两个表达式,op代表运算符号,那么:
expr1=(expr1) op (expr2)
等价于
expr1 op= expr2;
注意第一个表达式,有时候括号是不可缺少的,比如以下这个例子:
1 2 |
|
其意思是:
1 |
|
而不是:
1 |
|
这点尤为注意。
三、自增1和自减1
我们要实现一个数的自增1或者自减1,目前可以有以下两种方法:
a=a+1或者a+=1;
a=a-1或者a-=1;
但是由于在编写程序时自增1或者自减1用得非常频繁,java语言提供了两个专门用于变量的自增1和自减1的特殊运算符,其中++是自增1运算符号,可以使操作数自增1,--是自减1运算符号,可以使操作数自减1。比如下面这个例子就是自增1:
1 2 3 |
|
需要特别留意的是++和--运算符可以前置、后置,都是合法的语句,如a++和++a都是合法的,上面这两种写法其最终的结果都是是变量a的值加1了,但是它们之间也是有区别的,其区别是:表达是++a会先将a的值自增1,然后在使用变量a。而表达式a++是先使用了a的值,然后再让a的值自增1。也就是说在一些表达式,使用a++和使用++a得到的结果时不一样的。例如:
1 2 3 |
|
得到的结果是1,因为先使用了a的值后,才让a自增1。再看这个例子:
1 2 3 |
|
这时候b的值是2。再看看下面这个示例:
1 2 3 4 5 |
|
请读者上机测试,并回答为什么c最后的值是3。
最后再提一下++和--两个运算符都只能作用于变量,而不作用域表达式。如下面这个例子是非法的。
1 2 |
|
四、比较运算符
比较运算符也称为关系运算符,用于测试两个操作数之间的关系。使用关系运算符表达式的最终结果为 boolean 型,也就是其结果只有两个true和false。具体运算符号如下表所示:
运算符 |
== |
!= |
> |
< |
>= |
<= |
比较 |
等于 |
不等 |
大于 |
小于 |
大于等于 |
小于等于 |
例子 |
i==1; |
i!=1; |
i >1; |
i<1; |
i>=1; |
i<=1; |
结果 |
true |
false |
false |
false |
true |
true |
由上表所示,我们判断两个数是否相等使用两个等号(==),它与(!=)具有相同的优先级。比>、<、>=、<=的优先级要高,但是算术运算符的优先级比关系运算符高,也就是说i<a+100和i<(a+100)等结果都是一样。不同数据类型之间也可以进行比较,它们会被自动转换为相同的类型后再比较,如以下例子:
1 2 3 4 5 |
|
上面这些不同类型的变量进行比较是合法的。
五、逻辑运算符
运算符 |
& |
| |
! |
&& |
|| |
说明 |
与 |
或 |
非 |
阻断与 |
阻断或 |
示例 |
true&false |
True|false |
!false |
true&&false |
true||false |
结果 |
false |
true |
true |
false |
true |
逻辑运算符非常重要,尤其是在学习了后面的条件判断后,会大量使用这些逻辑运算符。
1、与运算
与运算符号有&和&&两个,表示必须两个条件都为true时,结果才能返回true。如:
(1>2)&&(1>3) (1>2)&&(3>1) (2>1)&&(1>3) (2>1)&&(3>1)
其对应比较运算过程就是
false&&false false&&true true&&false true&&true
也就是最后的结果就是前面三个的返回都是false,只有最后一个是true。
2、或运算
或运算符号有|和||两个,表示两个条件只要有一个满足为true,最后结果返回true。还是以上面例子说明如:
(1>2)&&(1>3) (1>2)&&(3>1) (2>1)&&(1>3) (2>1)&&(3>1)
其对应比较运算过程就是
false&&false false&&true true&&false true&&true
也就是最后的结果就是第一个返回为false,后面三个返回都是true。
3、取反运算符
取反运算符只有一个!,它是单元运算符,这个比较简单,如果是true就返回false,false就返回true,如下面的示例:
!(1>2) !(2>1)
其对应比较运算过程就是
!false !true
所以第一个返回是true,第二个返回是false。
4、组合的逻辑运算符
逻辑符可以组合使用,并结合上面比较运算符,形成一个复杂的条件判断,比如下面这个判断是否是闰年的条件判断式,闰年的判断条件是,如果此年份是4的陪数,但不是100的陪数,那么就是闰年,如果是100的陪数,还要是400的倍数才是闰年,实现代码如下:
1 2 |
|
5、 &和&&、|和||的区别
参与运算的都是boolean布尔类型,在上表中的逻辑运算符&和&&、|和||的示例中,结果的都是一样的,但是在运算时却有区别。&&和||有一些比较特殊的属性,其运算的顺序是从左至右进行判断的,但是对&&而言如果在判断时得到的结果是false时,那么后面的计算就不会继续,对||而言,如果在判断时得到的结果是true,那么后面的计算也不会继续,这种机制称之为阻断判断或者短路判断,在有些情况之下,这种机制可以提高程序运行的效率。
1 2 3 |
|
b, x, y的值分别是false, 1, 2。x和y虽然上面都有自增和自减的表达式,但是却并没有执行,那是因为x>y的结果是false,后面使用了短路判断&&,所以不管后面的表达式的结果是什么,最后的结果必然是false,所以后面的++x和--y其实都没有执行过,如果改成以下例子:
1 2 3 |
|
因为使用了&符号,所以b, x, y的值是false, 2, 1了。
六、条件运算符
java的条件运算符是三元运算符,也就是说有三个参数参与运算,其功能是对表达式条件进行判断,根据判断结果是true或者false两种情况赋予赋予不同的返回值,其语法如下:
表达式?值1:值2;
例如以下所示:
1 2 3 4 |
|
上面这个例子的意思就是说,如果a大于b,那么就返回3,否则就返回4,所以根据代码的执行,最后c的值就是3。
七、位运算符
位运算符在java的企业应用中使用的频率并不高,但是在一些追求效率和编写底层应用时,还是会用到位运算符,前面介绍的各种运算都是基本都是以字节作为最基本位进行运算的,而位运算符是以位(bit)作为运算单位的,所以要弄明白位运算符,必须要知道二进制表示法。
int a=1;//int 是 32 位 取最后的8位是 00000001按位位与运算符"&"就是实现参与运算的两个数对应的二进制位数执行与的操作。如果两个二进位均为1时,结果位才为1,否则就为0。前面介绍过,计算机都是采用补码的方式运行的,所以参与运算的数都是补码方式进行的。如下面所示例子:1、按位与
1 |
|
如代码所示00000001和00000101运算的结果是00000001。所以最后输出的结果是1 。
2、按位或
按位或运算符“|”就是实现参与运算的两个数对应的二进制位数执行或的操作。如果两个二进位均为0时,结果位才为0,否则就为1。我们继续以上面所示的例子:
1 |
|
如代码所示00000001和00000101运算的结果是00000001。所以最后输出的结果是5。
3、按位异或
按位异或运算符“^”就是实现参与运算的两个数对应的二进制位数执行异或的操作。如果两个二进位相同时,结果位为0,不同时就为否1,简称“同0异1”。也就是说两个都是1或者两个都是0时结果为0,否则为1。还是以上面作为例子
1 |
|
如代码所示00000001和00000101运算的结果是00000100。所以最后输出的结果是4
4、求反
求反运算符只是单目运算符,具有右结合性,这个功能比较简单,就是对参与运算的数的各二进位按位求反。但是这个结果需要补码的运算有所了解才行。
1 2 |
|
因为部门的第一位是符号位,按照补码的运算,对应的结果就是-2了。
5、左移
左移运算符“<<”其功能把“<<”左边的运算数的各二进位根据右边定义的数量全部左移若干位,移动的数位由右边所定义的数量决定。 移动时依据高位丢弃,低位补0的原则。
1 |
|
最后输出的结果是4,由上面的示例可知,每左移一位后,所得到的结果就是原来的数据乘以2,所以很多时候我们在做乘以2的操作是都是使用这个左移操作,以提高效率。
6、右移
右移运算符“>>”其功能把“>>”左边的运算数的各二进位根据右边定义的数量全部右移若干位,移动的数位由右边所定义的数量决定。 也是按照移动时依据高位丢弃,低位补0的原则。
1 |
|
结果是3,由上面的示例可知,和左移正好相反,每右移一位后,所得到的结果就是原来的数据除以2,所以很多时候我们在做除以2的操作是都也是使用这个由移操作,以提高效率。