Java是面向表達式的語言,Java中一個簡單表達式可以是下面任意一種:
● 常量:7、false。
● 單引號括起來的字符字面常量:'A'、'3'。
● 雙引號括起來的字符串字面常量:"foo"、"Java"。
● 任何正確聲明的變量名:myString、x。
● 任何用Java二元運算符(本章稍后將詳細討論)連接起來的兩個上述類型的表達式:x+2。
● 任何用Java一元運算符(本章稍后將詳細討論)修飾的單個上述類型的表達式:i++。
● 任何用小括號括起來的上述類型的表達式:(x+2)。
以及另外一些與本書后面將要學到的對象有關的表達式類型。
無論多么復雜的表達式都可以由不同類型的簡單表達式和括號嵌套組合而成,例如:((((4/x) + y) * 7) + z)。
一、 算術運算符
Java語言提供了許多基本的算術運算符,如表2-1所示。
表2-1 Java算術運算符
運算符 | 描述 |
+ | 加法 |
- | 減法 |
* | 乘法 |
/ | 除法 |
% | 取余數 10%3=1 |
+和-運算符也可作為一元運算符用於表示正負數:-3.7、+42。
除了簡單賦值運算符=,還有許多特定的復合賦值運算符,這些運算符將變量賦值和算術操作合並在一起,如表2-2所示。
表2-2 Java復合賦值運算符
運算符 | 描 述 |
+= | a+=b等價於a=a+b |
-= | a-=b等價於a=a-b |
*= | a*=b等價於a=a*b |
/= | a/=b等價於a=a/b |
%= | a%=b等價於a=a%b |
最后要介紹的兩個算術運算符是一元遞增運算符(++)和一元遞減運算符(--),用於將整數變量的值加1或減1,或者將浮點數變量的值加1.0或減1.0。稱它們為一元運算符是因為它們用於單個變量,而前面討論的二元運算符則連接兩個表達式的值。
一元遞增運算符和一元遞減運算符也可用於將字符變量在Unicode序列中向前或向后移動一個字符位置。例如,在下面的代碼片段中,字符變量c的值從'e'遞增為'f':
char c='e';
c++; //自加后,c='f'
遞增和遞減運算符可以以前綴或者后綴方式使用。如果運算符放在操作數之前(前綴模式),變量的遞增或遞減操作將在更新后的變量值被用於任何由它構成的賦值操作之前執行。例如,考慮下面的使用前綴遞增運算符的代碼片段,假設a和b在程序前面已經聲明為int變量:
a=1;
b=++a;
上述代碼執行后,變量a的值是2,變量b的值也是2。這是因為在第二行中變量a的遞增(從1到2)發生在它的值賦給b之前。因此這行代碼
b=++a;
在邏輯上等價於下面兩行代碼:
a=a+1;
b=a;
另一方面,如果運算符放在操作數之后(后綴模式),遞增或遞減操作發生在原來的變量值被用於任何由它構成的賦值操作之后。看一下以后綴方式使用遞增運算符的相同代碼片段:
a=1;
b=a++;
上述代碼執行后,變量b的值是1,而變量a的值是2。這是因為在第二行中變量a的遞增(從1到2)發生在它的值賦給b之后。因此這行代碼
b=a++;
在邏輯上等價於下面兩行代碼:
b=a;
a=a+1;
下面是一個稍微復雜一點例子,請閱讀附加的注釋以確保你能夠明白x最終是如何被賦值為10的:
int y=2;
int z=4;
int x=y++ * ++z;
上面語句中,先進行自加自減運算,++ 在變量后面,先運算后自加,y++值仍然為2 , ++在變量前面,先自加后運算,++z值為5,所以乘積為10.
稍后將會看到,遞增和遞減運算符通常和循環一起使用。
二、 關系和邏輯運算符
邏輯表達式以指定的方式比較兩個(簡單或者復雜)表達式exp1和exp2,決議出一個boolean值true或者false。
Java提供了表2-3所示的關系運算符來創建邏輯表達式。
Java關系運算符
運算符 | 含義 |
== | 等於 |
!= | 不等於 |
> | 大於 |
< | 小於 |
>= | 大於等於 |
<= | 小於等於 |
Java邏輯運算符
運算符 | 名稱 |
& | 與 |
| | 或 |
^ | 異或 |
&& | 短路與 |
|| | 短路或 |
! | 邏輯非 |
符號
|
名稱
|
功能說明
|
&&
|
邏輯與
|
兩個條件同時為true整個表達式才為true,否則為false
|
||
|
邏輯或
|
兩個條件有一個為true則整個表達式為true,否則為false
|
!
|
邏輯非
|
對原表達式值取反
|
下面這個例子用邏輯“與”運算符來編程實現邏輯表達式“如果x大於2.0且y不等於4.0”:
if((x>2.0)&&(y!=4.0)){……}
邏輯表達式常用於流程控制結構,稍后將進行討論。
三、 表達式求值和運算符優先級
如同本章前面提到的那樣,任何復雜的表達式都可以用分層嵌套的小括號構成,例如(((8 * (y + z)) + y) x)。編譯器通常按照從內到外,從左到右的順序對這樣的表達式求值。假設x、y、z按照下面的方式聲明並初始化:
int x=1;
int y=2;
int z=3;
下面的賦值語句右邊的表達式:
int answer=((8*(y+z))+y)*x;
將像下面這樣逐步求值:
沒有小括號時,根據運算符用於表達式求值的順序,某些運算符具有高於其他運算符的優先級。例如,乘除法先於加減法執行。通過使用小括號可以強制改變運算符的優先級,括號內的運算符比括號外的先執行。考慮下面的代碼片段:
int j=2+3*4;
int k= (2+3)*4;
代碼的第一行沒有使用括號,乘法操作比加法操作先執行,因此整個表達式的值為2+12=14,就像我們將表達式明確地寫成2+(3*4)一樣,當然這樣做沒有必要。
在代碼的第二行,括號被明確地放在操作2+3兩邊,因此加法操作將首先執行,然后求和結果乘以4作為整個表達式的值,即5*4=20。
回到前面的例子
if((x>2.0)&&(y!=4.0)){……}
注意到>和!=運算符優先級高於&&運算符,因此可以去掉嵌套的括號而變成下面這樣:
if(x>2.0 && y!=4.0){……}
然而,額外的括號並不會對代碼造成傷害,事實上它可以使表達式的目的更加清楚。
2.9.4 表達式類型
表達式類型是表達式最終求值結果的Java類型。例如給定下面的代碼片段:
double x=3.0;
double y=2.0;
if((x>2.0)&&(y!=4.0)){……}
表達式(x > 2.0) && (y != 4.0)求值結果為true,因此表達式(x > 2.0) && (y != 4.0)稱為boolean型表達式。在下面的代碼片段中:
int x=1;
int y=2;
int z=3;
int answer=((8*(y+z))+y)*x;
表達式((8 * (y + z)) + y) * x求值結果為42,因此表達式((8 * (y + z)) + y) * x稱為整型表達式。