public class test{ public static void main(String args[]){ int i = 3; float f = 3.14f; { i++; float f2 = f + 1f; System.out.println(f + " + 1 = " + f2 + "."); } System.out.println("i = " + i + "."); //System.out.println("f2 = " + f2 + "."); } }
编译,运行,会在标准输出看到:
3.14 + 1 = 4.1400003. i = 4.
如果去掉//System.out.println("f2 = " + f2 + ".");
的注释,也就是尝试在复合语句之外访问在复合语句内创建的变量,那么编译时会报错:
Exception in thread "main" java.lang.Error: Unresolved compilation problem: f2 cannot be resolved to a variable at test.main(test.java:13)
关于java的流程控制语句,本文不做扩展,本文着重深入了解表达式。
表达式有两种功能:每个表达式都产生一个值( value ),同时可能包含副作用( side effect ),比如可能修改某些值。
算术运算符用在数学表达式中,它们的作用和在数学中的作用一样。下表列出了所有的算术运算符。
表格中的实例假设整型变量A的值为10,变量B的值为20:
操作符 | 描述 | 例子 |
+ | 加法 - 相加运算符两侧的值 | A + B等于30 |
- | 减法 - 左操作数减去右操作数 | A – B等于-10 |
* | 乘法 - 相乘操作符两侧的值 | A * B等于200 |
/ | 除法 - 左操作数除以右操作数 | B / A等于2 |
% | 取模 - 右操作数除左操作数的余数 | B % A等于0 |
需要说明的:
int a = 500 / 0;
,系统会报出ArithmeticException
异常。
自增、自减运算符都是单目运算符,可以放在操作数之前,也可以放在操作数之后。操作数必须是整型或浮点型变量。
下面是一个例子test.java:
public class test{ public static void main(String args[]){ int a = 4, b; b = ++a; System.out.println(b); b = a++; System.out.println(b); } }
编译、运行,会在标准输出打印:
5 5
关系运算符属于二元运算符,用于程序中的变量和变量之间、变量和常量之间、其他类型的信息之间的比较。关系运算符的返回类型是boolean类型,当运算符对应的关系成立时,运算结果是true,否则结果是false。关系运算符通常用在条件语句中,来作为判断的依据。
关系运算符的种类和用法如下表:
运算符 | 作用 | 举例 | 操作数据 | 结果 |
> | 比较左方是否大于右方 | 'a' > 'b' | 整型、浮点型、字符型 | false |
< | 比较左方是否小于右方 | 156<456 | 整型、浮点型、字符型 | true |
== | 比较左方是否等于右方 | 'c' = = 'c' | 基本数据类型、引用型 | true |
>= | 比较左方是否大于等于右方 | 479 >= 426 | 整型、浮点型、字符型 | true |
<= | 比较左方是否小于等于右方 | 12.45 <= 45.5 | 整型、浮点型、字符型 | true |
!= | 比较左方是否不等于右方 | "y" != "t" | 基本数据类型、引用型 | false |
逻辑运算符包括:逻辑与(&&、&)、逻辑或(||、|)和逻辑非(!),返回值为boolean类型,操作数也必须是boolean类型的数据。在逻辑运算符中,除了逻辑非(!)是一元运算符之外,其余两个都是二元运算符,其用法和含义如下表:
运算符 | 含义 | 用法 | 结合方向 |
&&、& | 逻辑与 | op1&&op2 | 左到右 |
||、| | 逻辑或 | op1||op2 | 左到右 |
! | 逻辑非 | !op | 右到左 |
使用逻辑运算符进行逻辑运算,运行结果如下表:
表达式1 | 表达式2 | 表达式1&&表达式2 | 表达式1||表达式2 | !表达式1 |
true | true | true | true | false |
true | false | false | true | false |
false | false | false | false | true |
false | true | false | true | true |
从上表可以看出:
TIPS: 逻辑运算符“&&”和“&”都表示逻辑与, 逻辑运算符“||”和“|”都表示逻辑或, “&&”和“||”是短路的: “&&”在第一个表达式为false的时候,不会计算第二个表达式; “||”在第一个表达式为true的时候,不会计算第二个表达式; “&”和“|”是非短路的: 在任何情况下,都会计算第二个表达式。
下面看一个例子test.java:
public class test{ public static boolean func1(){ System.out.println("func1 is called."); return true; } public static boolean func2(){ System.out.println("func2 is called."); return false; } public static void main(String args[]){ boolean r; r = func2() && func1(); r = func2() & func1(); r = func1() || func2(); r = func1() | func2(); } }
编译、运行,会在标准输出打印:
func2 is called. func2 is called. func1 is called. func1 is called. func1 is called. func2 is called.
位运算符用于处理整型和字符型的操作数,对其内存进行操作,数值在内存中一律以补码的方式存储。例如int型常量7的二进制表示是00000000 00000000 00000000 00000111(正数的原码,反码,补码相同),-8的二进制表示是11111111 11111111 11111111 11111000(负数的补码是在原码的基础上,符号位不变,其余各个未取反,再加1);最高位为符号位,0表示正数,1表示负数。java语言提供的位运算符如下表:
运算符 | 含义 | 用法 |
~ | 按位取反 | ~op1 |
& | 按位与 | op1 & op2 |
| | 按位或 | op1 | op2 |
^ | 按位异或 | op1 ^ op2 |
下面看几个例子:
java提供的移位运算符如下表:
运算符 | 含义 | 用法 |
<< | 左移 | op1 << op2 |
>> | 右移 | op1 >> op2 |
>>> | 无符号右移 | op1 >>> op2 |
java中移位运算符有三种,操作数的类型只有byte、short、int、long和char五种。
48 << 1
,是将48的二进制数向左移一位,移位后的结果是96。
TIPS: 移位能让用户实现整数乘以或除以2的n次方的效果。例如y<<2与y*4的结果相同;y>>1与y/2的结果相同。总之,一个数左移n位,就是将这个数乘以2的n次方;一个数右移n位,就是将这个数除以2的n次方。
三元运算符是java中唯一一个三目运算符,其操作数有三个,第一个是条件表达式,其余两个是值。条件表达式成立时,取第一个值;条件表达式不成立时,取第二个值。示例代码如下:
boolean b = 20 < 45 ? true : false;
因为条件表达式20 < 45
成立,所以取第一个值,此例的结果是true。
赋值运算符=
是一个二元运算符,其功能是将右边的操作数所含的值赋给左边的操作数。语法格式如下:
[变量类型] 变量名 = 所赋的值;
左边的操作数必须是一个变量,右边的操作数可以是变量、常量或表达式。
赋值运算符是有返回值的。比如int x, y, z; x = y = z = 5;因为赋值运算符是右结合的,所以先计算z = 5,此时z的值为5,并且z = 5这个表达式的值为5,所以x = y = z = 5转换成了x = y = 5,然后计算y = 5,此时y的值为5,并且y = 5这个表达式的值是5,所以x = y = 5转换成了x = 5,此时x的值是5。所以最终x、y、z的值都是5。
混合赋值运算符包括:
运算符 | 描述 | 例子 |
+= | 加和赋值操作符,它把左操作数和右操作数相加赋值给左操作数 | C + = A等价于C = C + A |
-= | 减和赋值操作符,它把左操作数和右操作数相减赋值给左操作数 | C - = A等价于C = C - A |
*= | 乘和赋值操作符,它把左操作数和右操作数相乘赋值给左操作数 | C * = A等价于C = C * A |
/= | 除和赋值操作符,它把左操作数和右操作数相除赋值给左操作数 | C / = A等价于C = C / A |
%= | 取模和赋值操作符,它把左操作数和右操作数取模后赋值给左操作数 | C%= A等价于C = C%A |
<<= | 左移位赋值运算符 | C << = 2等价于C = C << 2 |
>>= | 右移位赋值运算符 | C >> = 2等价于C = C >> 2 |
&= | 按位与赋值运算符 | C&= 2等价于C = C&2 |
^ = | 按位异或赋值操作符 | C ^ = 2等价于C = C ^ 2 |
|= | 按位或赋值操作符 | C | = 2等价于C = C | 2 |
instanceof运算符是一个二元运算符,只用于对象引用变量,它的作用是测试一个对象是否为特定类型(类类型或接口类型)的对象。用法:
( Object reference variable ) instanceof (class/interface type)
如果左侧的对象引用变量 是class的实例 或者是class或interface的子类的实例,那么返回true,否则返回false。
下面是一个例子test.java:
interface i{ } class c implements i{ } class c2 extends c{ } public class test{ public static void main(String args[]){ c2 obj = new c2(); System.out.println(obj instanceof c); System.out.println(obj instanceof c2); System.out.println(obj instanceof i); } }
编译、运行,会在标准输出打印:
true true true
在同一个表达式中,先计算优先级高的运算符,再计算优先级低的运算符,对于优先级相同的运算符,按照结合性来确定计算顺序,如果运算符是左结合的,就先计算左边的运算符,如果运算符是右结合的,就先计算右边的运算符。
序列号 |
符号 |
名称 |
结合性(与操作数) |
目数 |
说明 |
1 |
. |
点 |
从左到右 |
双目 |
|
( ) |
圆括号 |
从左到右 |
|
|
|
[ ] |
方括号 |
从左到右 |
|
|
|
2 |
+ |
正号 |
从右到左 |
单目 |
|
- |
负号 |
从右到左 |
单目 |
|
|
++ |
自增 |
从右到左 |
单目 |
前缀增,后缀增 |
|
- - |
自减 |
从右到左 |
前缀减,后缀减 |
||
~ |
按位非/取补运算 |
从右到左 |
单目 |
|
|
! |
逻辑非 |
从右到左 |
单目 |
||
3 |
* |
乘 |
从左到右 |
双目 |
|
/ |
除 |
从左到右 |
双目 |
整数除法:取商的整数部分,小数部分去掉,不四舍五入 |
|
% |
取余 |
从左到右 |
双目 |
|
|
4 |
+ |
加 |
从左到右 |
双目 |
|
- |
减 |
从左到右 |
双目 |
|
|
5 |
<< |
左移位运算符 |
从左到右 |
双目 |
|
>> |
带符号右移位运算符 |
从左到右 |
双目 |
|
|
>>> |
无符号右移 |
从左到右 |
双目 |
|
|
6 |
< |
小于 |
从左到右 |
双目 |
|
<= |
小于或等于 |
从左到右 |
双目 |
|
|
> |
大于 |
从左到右 |
双目 |
|
|
>= |
大于或等于 |
从左到右 |
双目 |
|
|
instanceof |
确定某对象是否属于指定的类 |
从左到右 |
双目 |
|
|
7 |
== |
等于 |
从左到右 |
双目 |
|
!= |
不等于 |
从左到右 |
双目 |
|
|
8 |
& |
按位与 |
从左到右 |
双目 |
|
9 |
| |
按位或 |
从左到右 |
双目 |
|
10 |
^ |
按位异或 |
从左到右 |
双目 |
|
11 |
&& |
短路与 |
从左到右 |
双目 |
|
12 |
|| |
短路或 |
从左到右 |
双目 |
|
13 |
? : |
条件运算符 |
从右到左 |
三目 |
|
14 |
= |
赋值运算符 |
从右到左 |
双目 |
|
+= |
混合赋值运算符 |
|
|||
-= |
|
||||
*= |
|
||||
/= |
|
||||
%= |
|
||||
&= |
|
||||
|= |
|
||||
^= |
|
||||
<<= |
|
||||
>>= |
|
||||
>>>= |
|
概括而言,优先级从高到低的顺序是:后缀运算符(点、圆括号、方括号)、单目运算符、算数运算符、移位运算符、关系运算符和instanceof、位运算符、逻辑运算符、条件运算符、赋值运算符、混合赋值运算符。
右结合的运算符有:所有的单目运算符、条件运算符、所有的赋值运算符。其余的运算符都是左结合的。