- Java程序設計與實踐教程(第2版)
- 楊麗萍 王薇 張焱焱主編 北京云班科技有限公司副主編
- 4591字
- 2019-07-01 11:10:51
2.5 運算符和表達式
運算符也稱為操作符,用于對數據進行計算和處理,或改變特定對象的值。運算符按其操作數的個數來分,可分為一元運算符、二元運算符和三元運算符。按照運算符對數據的操作結果分類,運算符可以分為以下幾種。
算術運算符:+, -, *, /, %, ++, --
賦值運算符:=
擴展賦值運算符:+=, -=, *=, /=, %=, &=, \=, ^=, >>=,<<=, >>>=
關系運算符:<, >, >=, <=, ==, ! =
布爾邏輯運算符:! , &&, ||
位運算符:>>, <<, >>>, &, |, ^, ~
條件運算符:(? :)
其他運算符:包括分量運算符“· ”,下標運算符“[]”,實例運算符“instance of”,內存分配運算符“new”,強制類型轉換運算符(類型),以及方法調用運算符“(?。钡取?/p>
表達式是運算符、常量和變量的組合。Java的表達式既可以單獨組成語句,又可以出現在循環條件測試、變量說明、方法的調用參數等場合。
2.5.1 算術運算符和算術表達式
算術表達式由操作數和算術運算符組成。算術運算符的操作數必須是數字類型。算術運算符不能用在布爾類型上,但是可以用在char類型上,因為實質上在Java中,char類型是int類型的一個子集。Java的算術運算符分一元運算符和二元運算符兩種。一元算術運算符運算一次只對一個變量進行操作,二元算術運算符運算一次對兩個變量進行操作。
1.一元算術運算符及表達式
一元算術運算符涉及的操作數只有一個,由一個操作數和一元算術運算符構成一個算術表達式。一元算術運算符共有4種,如表2-5所示。
表2-5 一元算術運算符

一元加和一元減運算符僅僅表示某個操作數的符號,其操作結果為該操作數的正值或負值。
增量運算符將操作數加1,如對浮點數進行增量操作,則結果為加1.0。
減量運算符將操作數減1,如對浮點數進行減量操作,則結果為減1.0。
例如:++x與x++的結果均為x=x+1。
——y與y——的結果均為y=y-1。
但是,如果將增量運算與減量運算表達式再作為其他表達式的操作數使用時,i++(i——)與++i(——i)是有區別的,解釋如下:
i++在使用i之后,使i的值加1,因此執行完i++后,整個表達式的值為i,而i的值變為i+1。
++i在使用i之前,使i的值加1,因此執行完++i后,整個表達式和i的值均為i+1。
對于i——與——i的區別有著同樣的解釋。
例如,假設a=5, b=10,則表達式c=(a++)*(——b)的計算過程為:a先使用再加1, b先減1再使用,所以結果為:b=b-1=9, c=a*b=4, a=a+1=6。若x=5, m=0, x+=x+++(x+++m)的值則為16。
【例2-14】 一元算術運算符的使用。
//文件名:ArithmaticTest1.java public class ArithmaticTest1 { public static void main(String args[] ){ int a=9; int b=-a; //b=-9 int i=0; int j=i++; //i=1, j=0 int k=++j; //j=1, k=1 System.out.println("a="+a); System.out.println("b="+b); System.out.println("i="+i); System.out.println("j="+j); System.out.println("k="+k); } }
程序的運行結果如下:
a=9 b=-9 i=1 j=1 k=1
2.二元算術運算符及表達式
二元算術運算符涉及兩個操作數,由兩個操作數和二元算術運算符構成一個算術表達式。二元算術運算符不改變操作數的值,而是返回一個必須賦給變量的值。二元算術運算符如表2-6所示。
表2-6 二元算術運算符

這些算術運算符適用于所有數值型數據類型。但要注意,如果操作數全為整型,那么,只要其中一個為long型,則表達式結果也為long型;其他情況下,即使兩個操作數全是byte型或short型,表達式結果也為int型;如果操作數為浮點型,那么,只要其中有一個為double型,表達式結果就是double型;只有兩個操作數全是float型或其中一個是float型而另外一個是整型時,表達式結果才是float型。另外,當“/”運算和“%”運算中除數為0時,會產生異常。
與C、C++不同,對取模運算符“%”來說,其操作數可以為浮點數,如45.4%10=5.4。
【例2-15】 二元運算符的使用。
//文件名:ArithmaticTest2.java public class ArithmaticTest2{ public static void main(String args[] ){ int a=7/2; //結果為3,兩個操作數都為int型,結果也為int型 double b=7/2.0; //結果為3.5,其中一個操作數為double型,結果也為double型 byte x=5, y=6; long r=90L; long g=r/a; //結果為30L,其中一個操作數為long型,結果也為long型 int c=x*y; //結果為30,兩個操作數都為byte型,結果為int型 float z=8.3f, w=2.9f; float d=z+w; //結果為11.2f,兩個操作數都為float型,結果也為float型 float e=c-z; //結果為21.7f,其中一個操作數為float型,結果也為float型 double f=b%a; //結果為0.5,取模運算,其中一個操作數為double型 } }
Java對加運算符進行了擴展,使它能夠進行字符串的連接,如"abc"+"de",得到字符串"abcde"。
2.5.2 案例分析:溫度轉換
1.案例描述
編寫一個應用程序,它讀入一個華氏溫度值F,將其轉換為攝氏溫度值C并顯示出結果。
2.案例分析
根據案例描述中的要求,分析如下:要將華氏溫度轉換為攝氏溫度并顯示,需要溫度的轉換公式C =5.0/9.0 * (F-32),由此即可得出相應結果。
3.案例實現
本例的代碼如下:
//文件名:DoesHuan.java import java.util.Scanner; public class DoesHuan{ public static void main(String args[]){ int F; double C; Scanner input= new Scanner(System.in); System.out.println("請輸入一個華氏溫度F:"); F = input.nextInt(); C = 5.0 / 9.0 * (F -32); System.out.printf("轉換成攝氏溫度C="+C); } }
4.歸納與提高
本例中,應掌握基本變量的定義和使用。需要注意的是,數據的類型要根據數據存儲的值來正確選擇。
2.5.3 賦值運算符和賦值表達式
賦值表達式的組成是這樣的:在賦值運算符的左邊是變量,右邊是表達式。表達式值的類型應與左邊的變量類型一致或可以轉換為左邊的變量類型。賦值運算符分為賦值運算符“=”和復合賦值運算符兩種。
1.賦值運算符
賦值運算符“=”把一個表達式的值賦給一個變量,在賦值運算符兩側的類型不一致的情況下,如果左側變量類型的級別高,則右側的數據被轉化為與左側相同的高級數據類型后賦給左側變量;否則,需要使用強制類型轉換運算符。例如:
byte b=121; int j; j=b+1; //把表達式b+1的值賦給變量j
2.復合賦值運算符
在賦值運算符“=”前加上其他運算符,即構成復合賦值運算符。例如,a+=3等價于a=a+3。
表2-7列出了Java中的復合賦值運算符及等價的表達式。
表2-7 Java中的擴展賦值運算符

復合賦值運算符的特點是可以使程序表達簡練,并且還能提高程序的編譯速度。
例如:
b%=6等價于b=b%6。
a+=a*=b-=(a=6)/(b=2)則包含以下4步運算:
第一步,a=6, b=2, a/b=3
第二步,b=b-a/b=-1
第三步,a=a*b=-6
第四步,a=a+a=-12
【例2-16】 賦值運算符的例子。
//文件名:OperatorSample.java public class OperatorSample{ public static void main(String args[]) { byte a=60; short b=4; int c=30; long d=4L; long result=0L; result+=a-8; System.out.println("result+=a-8:"+result); result*=b; System.out.println("result*=b:"+result); result/=d+1; System.out.println("result/=d+1:"+result); result-=c; System.out.println("result-=c:"+result); result%=d; System.out.println("result%=d:"+result); } }
程序的運行結果如下:
result+=a-8:52 result*=b:208 result/=d+1:41 result-=c:11 result%=d:3
2.5.4 關系運算符和關系表達式
關系運算符用來比較兩個操作數,由兩個操作數和關系運算符構成一個關系表達式。關系運算符的操作結果是布爾類型的,即結果為真或假。關系運算符都是二元運算符,一共分為6種,如表2-8所示。
表2-8 關系運算符

關系運算的結果返回true或false,而不是C/C++中的1或0。關系運算符常與邏輯運算符一起使用,作為流程控制語句的判斷條件。例如:
if (a>=b&&b! =c) sum+=3;
2.5.5 邏輯運算符和邏輯表達式
邏輯運算符用來連接關系表達式,對關系表達式的值進行邏輯運算,由關系表達式和邏輯運算符構成邏輯表達式。
邏輯運算符共有3種,即邏輯與(&&)、邏輯或(||)和邏輯非(!),其操作結果也都是布爾型的,如表2-9所示。
表2-9 邏輯運算符表

&&、||為二元運算符,實現邏輯與、邏輯或。
!為一元運算符,實現邏輯非。
對于布爾邏輯運算,先求出運算符左邊表達式的值,若是或運算,其左邊表達式的值為true,則不必對運算符右邊的表達式再進行運算,整個表達式的結果為true;若是與運算,其左邊表達式的值為false,則不必對右邊的表達式求值,整個表達式的結果為false。
【例2-17】 關系運算符的使用。
//文件名:RelationAndConditionTest1.java public class RelationAndConditionTest1{ public static void main(String args[]) { int x=3; int y=6; boolean z=x==y; //z=false System.out.println("x="+x); System.out.println("y="+y); System.out.println("x==y="+z); double w=0.3e-15; //如果w=0,則&&左邊表達式值為假,右邊不會再計算,不會出現"被零除"錯誤 if(w! =0 && (x+y)/w<Double.MAX_VALUE) System.out.println("(x+y)/w="+(x+y)/w); else //分母不為0并且商沒有發生溢出時輸出表達式的值 System.out.println("運算結果溢出!"); } }
程序的運行結果如下:
x=3 y=6 x==y=false (x+y)/w=3.0e+16
【例2-18】 用另一種方法實現上例。
//文件名:RelationaAndConditionTest2.java public class RelationaAndConditionTest2 { public static void main(String args[]){ int x=3; int y=6; boolean z; //z=false if (x==y) z=true; else z=false; //如果x與y相等,z的值為true,否則為false System.out.println("x="+x); System.out.println("y="+y); System.out.println("x==y="+z); double w=0.3e-15; //如果w=0,則||左邊表達式值為真,右邊不會再計算,不會出現"被零除"錯誤 if (w==0 ||(x+y)/w>=Double.MAX_VALUE) //商無窮大或超出最大值時顯示"運算結果溢出!" System.out.println("運算結果溢出!"); else //分母不為0并且商沒有發生溢出時輸出表達式的值 System.out.println("(x+y)/w="+(x+y)/w); } }
程序的運行結果如下:
x=3 y=6 x==y=false (x+y)/w=3.0e+16
可以看出,例2-17與例2-18的運行結果是一樣的。
關系運算符和邏輯運算符的優先級如下:!的優先級最高,其次為>、>=、<、<=,然后是&&,最后是||。和算術運算符一樣,括號可以改變關系運算符和布爾邏輯運算符的運算順序,參見例2-19。
【例2-19】 關系運算符的優先級示例。
//RelationAndConditionTest3.java public class RelationAndConditionTest3{ public static void main(String args[]) { int x=3; int y=6; boolean w=true; boolean z=x<0||x<y&&x>0; boolean u=! w||x<0; boolean v=! w&&y>0; System.out.println("x="+x); System.out.println("y="+y); System.out.println("z="+z); System.out.println("w="+w); System.out.println("u="+u); System.out.println("v="+v); } }
程序的運行結果如下:
x=3 y=6 z=true w=true u=false v=false
2.5.6 條件運算符和條件表達式
條件運算符是三元運算符,用?和:表示。三元條件表達式的一般形式為:
expression1? expression2:expression3
其中表達式expression1應該是關系或布爾邏輯表達式,其計算結果為布爾值。如果說該值為true,則計算表達式expression2,并將計算結果作為整個條件表達式的結果;如果為false,則計算表達式expression3,并將計算結果作為條件表達式的結果。
例如:
a=30; b=a>16?160:180;
等號右邊為條件表達式,a>16的計算結果為true,所以b=160。三元條件運算符可以代替if-else語句的功能,上述條件表達式等價于:
if (a>16) b=160; else b=180;
【例2-20】 條件運算符的例子。
//文件名:OperatorSample2.java public class OperatorSample2 { public static void main(String args[]){ int x=0; boolean isFalse=false; System.out.println("x="+x); x=isFalse?4:7; System.out.println("x="+x); } }
程序的運行結果如下:
x=0 x=7
2.5.7 位運算符和移位運算符
使用任何一種整數類型時,可以直接使用位運算符對這些組成整型的二進制位進行操作。這意味著可以利用屏蔽和置位技術來設置或獲得一個數字中的單個位或幾位,或者將二進制位向右或向左移動。由位運算符和整型操作數組成位運算表達式。
Java中提供了如表2-10所示的位運算符。
表2-10 位運算符

從表2-10可以看出,位運算符中,除~以外,其余均為二元運算符。為了表述方便,把位運算符分為位邏輯運算符(包括~、&、|和^)和移位運算符(包括>>、<<和>>>)。
【例2-21】 位邏輯運算符的舉例。
//文件名:LogicOperator.java public class LogicOperator { public static void main(String args[]) { int a=20, b=14; System.out.println("a&b="+(a&b)); System.out.println("a|b="+(a|b)); System.out.println("a^b="+(a^b)); System.out.println("~a="+(~a)); } }
程序的運行結果如下:
a&b=4 a|b=30 a^b=26 ~a=-21
在進行位邏輯運算時,如果兩個操作數的數據長度不同,如x|y, x為long型,y為int型(或char型),則系統首先會將y的左側32位(或48位)填滿。若y為正數,則填滿0,若y為負數,則左側填滿1。這樣,位邏輯運算表達式返回兩個操作數中數據長度較長的數據類型。
移位運算符有左移(<<)、右移(>>)、無符號右移(>>>)。
1.左移運算符
左移運算符將比特位依次左移,右端空出來的位填0,如圖2-2所示。

圖2-2 左移運算示意圖
例如,假設a=00000001b,若
執行a<<1,則a=00000010b=2;
執行a<<2,則a=00000100b=4;
執行a<<3,則a=00001000b=8。
從上述結果可以看出,只要結果不發生溢出,每左移1位,相當于a*2;左移2位,相當于a*4;以此類推,左移n位,相當于a*2n。
既然每次左移都可以使原來的操作數乘2,那就可以使用這個方法完成快乘2的操作。但是需要注意的一點是,如果將1移進高位,那么該值將變為負值。
【例2-22】 位左移運算符的舉例。
//文件名:MultiByTwo.java public class MultiByTwo{ 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
2.右移運算符
右移運算符表示右移一位,被移動的數若為正數,最左端填0;若為負數,則最左端填1,如圖2-3所示。也就是說,不論移位的數據是正數還是負數,移位時,符號位保持不變。

圖2-3 右移運算示意圖
例如,a=+16=00010000b,若
執行a>>1, a=00001000b=+8;
執行a>>2, a=00000100b=+4;
執行a>>3, a=00000010b=+2。
又如,b=-16,用8位表示,其補碼為11110000b,若
執行b>>1,則其補碼為11111000b,其十進制數結果為-8;
執行b>>2,則其補碼為11111100b,其十進制數結果為-4;
執行b>>3,則其補碼為11111110b,其十進制數結果為-2。
從上面兩例可以看出,右移運算實際上是一種補碼的右移運算,在運算過程中,操作數的符號位不發生改變,并且,每右移1位,相當于a/2;右移2位,相當于a/4;以此類推。可以利用這個特點將一個整數進行快速的除2操作。當然,一定要確保不會將該數原有的任何一位移出。
右移時,被移走的最高位(最左邊的位)由原來最高位的數字補充。因此,-1右移的結果總是-1。
3.無符號右移運算符
除法的效果,只是在需要移位的時候使用。它用來將一個無符號數的各個二進制位右移若干位,移出的低位被舍棄,高位補0。即操作對象為無符號數。
例如,如果a=11101010,則a>>>2的值為00111010。
下面的程序段說明了無符號右移運算符>>>。在本例中,變量a被賦值為-1,用二進制表示就是32位全是1。然后這個值被無符號右移24位,當然在它的左邊總是補0。這樣得到的值255被賦給變量a。
int a=-1; a=a>>>24;
下面用二進制形式進一步說明該操作:
11111111 11111111 11111111 11111111 //int型-1的二進制值 >>>24 //無符號右移24位 00000000 00000000 00000000 11111111 //int型255的二進制值
由于無符號右移運算符>>>只是對32位和64位的值有意義,所以在表達式中過小的值總是被自動擴大為int型。
知識提示 Java中沒有<<<運算符。
2.5.8 運算符優先級
在對一個表達式進行運算時,要按照運算符的優先順序從高到低進行運算,運算符的優先級是指同一個表達式中多個運算符被執行的次序。
Java運算符的優先級與C++語言的幾乎完全一樣,圓括號的優先級最高,賦值運算符的優先級最低。在運算過程中,可以使用圓括號改變運算的次序。Java中運算符的優先級如表2-11所示。
表2-11 Java中運算符的優先級順序

另外,運算符還具有結合特性,即左結合特性(從左至右)和右結合特性(從右至左)。對左結合特性很好理解,表達式計算從左至右計算。對于右結合特性,賦值運算符的使用就是個很好的例子。
2.5.9 案例分析:運算符優先級
1.案例描述
創建一個程序,說明運算符的優先級。
2.案例分析
根據案例描述的信息,結合運算符的優先級順序,利用幾種運算符的運算規則,體現運算符的優先級的次序。
3.案例實現
本例的代碼如下:
//文件名:OperatorSample3.java public class OperatorSample3{ public static void main(String agrs[]) { int a, b; boolean d; float c, z, f; a=5; b=8; c=a+++1; d=a>b&&b>c; z=a+c*b; f=(a+c)*b; System.out.println("a="+a); System.out.println("b="+b); System.out.println("c="+c); System.out.println("d="+d); System.out.println("z="+z); System.out.println("f="+f); } }
程序的運行結果如下:
a=6 b=8 c=6.0 d=false z=54.0 f=96.0
4.歸納與提高
本例通過利用算術運算符,關系運算符和邏輯運算符的運算規則,借助其優先級的前后次序,進而說明在運算中要注意優先級的順序,以期達到正確的運算結果。要著重掌握各個運算符的優先級的先后次序,以及運算時的結合次序。
- DevOps with Kubernetes
- Koa開發:入門、進階與實戰
- 小程序開發原理與實戰
- Learning FuelPHP for Effective PHP Development
- Android項目實戰:手機安全衛士開發案例解析
- Serverless Web Applications with React and Firebase
- Backbone.js Testing
- STM8實戰
- 從零開始構建深度前饋神經網絡:Python+TensorFlow 2.x
- Keil Cx51 V7.0單片機高級語言編程與μVision2應用實踐
- Mastering OpenStack
- C#程序設計基礎與實踐
- Elasticsearch實戰(第2版)
- Mastering Java EE Development with WildFly
- 大話統計學(溢彩實訓版):基于R語言+中文統計工具