第2章 認識資料處理與表達式
計算機主要的特點之一就是具有強大的計算能力,能把從外界得到的資料輸入計算機,并通過程式來進行運算,最後輸出所要的結果。下面我們從資料處理的角度來認識Java。Java中任何資料處理的結果都是由表達式來完成的。通過不同的操作數與運算符的組合就可以得到程式設計者所要的結果。在本章中,我們将認識變量與常數的使用以及Java語言中常見的基本資料類型,其中的資料類型代表變量使用記憶體空間的大小,而變量用于存放程式執行時的資料(如圖2-1所示)。同時,我們還會示範如何進行各種資料類型之間的轉換。

本章的學習目标
- 變量與常數的使用
- 基本資料類型
- 自動資料類型轉換
- 基本輸入與輸出
- 強制類型轉換
2.1 資料類型介紹
當程式執行時,外界的資料進入計算機後,當然要有一個“栖身”之處,這時系統就會配置設定一個記憶體空間給這份資料。而在程式代碼中,我們所定義的變量(Variable)與常數(Constant)的主要用途就是存儲資料,并用于程式中的各種計算與處理。Java語言是一種強類型(Strongly Type)語言,意思是指:“變量在使用之前,必須聲明其資料類型,我們可以任意存取這個變量的值,但是變量所聲明的資料類型在程式中不可以随意變更。”
Java的資料類型可以分成“基本(Primitive)資料類型”與“引用(Reference)資料類型”。基本資料類型在聲明時會先配置設定記憶體空間,目前Java共有byte、short、int、long、float、double、char和boolean八種基本資料類型。而引用資料類型則不會在聲明時就配置設定記憶體空間,必須另外指定記憶體空間,也就是說,引用資料類型的變量值其實記錄的是一個記憶體位址,這種類型的資料類型有數組、字元串。圖2-2說明了基本資料類型中8種資料類型的分類關系。
2.1.1 整數類型
整數類型用來存儲不含小數點的資料,與數學上的意義相同,如-1、-2、-100、0、1、2、100等。整數類型分為byte(位元組)、short(短整數)、int(整數)和long(長整數)4種,按資料類型的存儲機關及數值表示的範圍整理如表2-1所示。
【範例程式:CH02_01】
01 // CH02_01.java,位元組資料類型聲明的執行個體
02 public class CH02_01 {
03 public static void main (String args[ ]) {
04 byte a=123; // 聲明位元組資料類型并賦初值
05 byte b=1234;
06 }
07 }
【程式的編譯結果】
程式的編譯結果可參考圖2-3。
程式CH02_01經編譯後,編譯器提示程式中有一處錯誤,并說明是資料類型聲明的錯誤,byte(位元組)可表示的數值範圍是-127~128,因而第05行導緻編譯失敗,因為1234已經超出byte類型數值的範圍,而第04行編譯成功,因為123符合所規定的範圍。我們可以把第05行程式修改為“short b=1234”,即采用short(短整數)資料類型,這樣1234就包括在資料類型指定的範圍内了。
2.1.2 浮點數類型
浮點數(Floating Point)就是帶有小數點的數字,也就是我們在數學上所指的實數。由于程式設計語言普遍應用于許多科學的精密運算,是以整數所能表示的數值範圍顯然不足,這時浮點數就派上用場了。
浮點數的表示方法有兩種,一種是小數點表示法;另一種是科學記數法表示法。例如,3.14和-100.521是小數點表示法,而6e-2和3.2E-18是科學記數法表示法。在科學記數法表示法中,其中的e或E代表以10為底數,例如6e-2,其中6被稱為有效數值,-2被稱為指數。表2-2所示為小數點表示法與科學記數法表示法的對照表。
尤其是當需要進行小數基本四則運算時,或者數學運算上的開平方根(
)與求三角函數的正弦、餘弦等運算時,運算結果需要精确到小數點後幾位,這時就會使用到浮點數類型。Java浮點數類型包含float(浮點數)和double(雙精度浮點數),如表2-3所示。
【範例程式:CH02_02】
01 // CH02_02.java,浮點數與雙精度浮點數的聲明
02 public class CH02_02 {
03 public static void main(String args[ ] ){
04 float a=12.5f;
05 double b=123456.654d;
06 System.out.println("a="+a);
07 System.out.println("b="+b);
08 }
09 }
【程式的執行結果】
程式的執行結果可參考圖2-4。
【程式的解析】
程式代碼的第04行聲明了一個名稱為a的浮點數,它被賦予的初值為12.5f,該數值的後面多加了一個字母“f”作為float(浮點數)的标記,程式代碼的第05行聲明了一個名稱為b的浮點數,它被賦予的初值是123456.654d,這個數值的後面多加了一個字母“d”作為double(雙精度浮點數)的标記。數值後面的大寫字母“F”和大寫字母“D”與它們的小寫字母表示的意思相同。通常在編寫程式時,在浮點數後面有沒有這樣的标記并無太大的關系。
2.1.3 布爾類型
布爾(Boolean)類型的變量用于關系運算的判斷或邏輯運算的結果,例如判斷“5>3”是否成立,判斷結果的布爾值隻有true(真)和false(假)兩種。
【範例程式:CH02_03】
01 // CH02_03.java,布爾值的聲明與列印輸出
02 public class CH02_03 {
03 public static void main(String args[]) {
04 boolean logic=true; // 設定布爾變量的值為false
05 System.out.println("聲明的布爾值="+logic);
06 }
07 }
程式的執行結果可參考圖2-5。
2.1.4 字元類型
在Java中,字元資料類型為char,它是一種使用16位(16-bit)二進制數所表示的Unicode字元。表2-4列出了char資料類型的存儲機關及資料值表示的範圍。
在Java程式中,可以使用單引号将字元引起來,以此表示字元資料類型的值。大家要特别注意的是,字元數值是用單引号标注單個字元而不是使用雙引号,這和字元串(例如"學無止境")以雙引号标注是不一樣的,例如字元變量的指派方式:
char ch1='X';
另外,也可以用'u十六進制數字'的方式來表示字元的值,u表示Unicode碼格式。不同的字元有不同的資料表示值,如字元@的資料表示值為'u0040',字元A的資料表示值為'u0041'。
【範例程式:CH02_04】
01 // CH02_04.java,字元資料類型聲明的執行個體
02 public class CH02_04 {
03 public static void main(String args[ ]) {
04 char ch1='X';
05 char ch2='\u0058'; //Unicode編碼的寫法
06 System.out.println("ch1="+ch1);
07 System.out.println("ch2="+ch2);
08 }
09 }
程式的執行結果可參考圖2-6。
第04、05行:兩種不同方式的字元資料類型寫法,可以直接寫字元'X',如果知道該字元的Unicode編碼,也可以用字元對應的Unicode編碼的十六進制數值來作為字元值。
另外,字元類型的資料中除了一般的字元外,還有一些特殊的字元無法使用鍵盤來輸入或直接顯示在螢幕上。這時必須在字元前加上反斜杠“”來通知編譯器将後面的字元當成一個特殊字元,就是所謂的轉義序列字元(Escape Sequence Character),用于某些特殊的控制功能。例如,'n'是表示換行功能的轉義序列字元。有關各種轉義序列字元與Unicode碼之間的關系,請參考表2-5的說明。
2.2 變量與常數
前文已經介紹過,外界的資料進入計算機需要有一個“栖身”之所,系統會配置設定記憶體空間用于存儲這些資料。在程式代碼中所定義的變量(Variable)與常數(Constant)就讓編譯器在程式投入系統運作時給這些變量與常數配置設定記憶體空間,以便參與程式中的各種運算與處理。變量是一種可變動的數值,它的數值會根據程式内部的處理與運算進行變更。簡單來說,變量與常數都是程式設計人員用來存取記憶體中資料内容的一個辨別碼,兩者最大的差異在于變量的内容會随着程式執行而改變,但常數則會固定不變。
2.2.1 變量與常數的聲明
變量是具備名稱的一塊記憶體空間,用來存儲可變動的資料内容。當程式需要存取某個記憶體的内容時,就可以通過變量名稱将資料從記憶體中取出或寫入這個記憶體空間。在使用變量前,必須對變量進行聲明,Java語言的變量聲明語句可分為“資料類型”與“變量名稱”兩部分。聲明語句的文法如下:
資料類型變量名稱; // 符号“;”表示語句的結束
假如我們聲明兩個整數變量num1和num2,其中int為Java語言中用于聲明整數類型的關鍵字(keyword):
int num1=30;
int num2=77;
這時Java會分别自動配置設定4位元組的記憶體空間給變量num1和num2,它們的存儲值分别為30和77。當程式運作過程中需要存取這塊記憶體空間的内容時,就可以直接使用變量名稱num1與num2來進行存取,如圖2-7所示。
以上為單個變量聲明的程式語句,當同時要聲明多個相同資料類型的變量時,可使用逗号“,”來分隔變量名稱,例如:
long apple, banana ; // 同時聲明多個long類型的變量,以逗号作為分隔符
完成變量的聲明後,有些變量可根據需要賦初值,就是在變量聲明的語句中加入初值的設定,文法如下:
資料類型變量名稱=初值;
例如:
int apple =5; // 聲明單個int類型的變量,并把它的初值設定為5
boolean a=true,b=false; // 同時聲明多個boolean類型的變量,并賦初值
在賦初值時,注意資料類型的字元和浮點數的指派。給char資料類型賦初值有三種方法:字元、Unicode碼以及ASCII碼,其中初值為字元、Unicode碼格式時,必須在字元的左右兩邊各加上單引号“'”。如下所示:
char apple ='@'; //用字元表示方式來賦初值“@”
char apple ='\u0040'; //用“@”字元對應的Unicode碼格式來賦初值,即“\u0040”
char apple =64; //用“@”字元對應的ASCII碼“64”來賦初值,ASCII碼用十進制數表示
2.2.2 變量與常數的命名規則
在Java語言中,辨別符(Identifier)用來命名變量、常數、類、接口、方法,辨別符是使用者自行命名的文字串,由英文大小寫字母、數字或下畫線“_”等符号組合而成,變量命名有一定的要求與規則:
- 必須為合法的辨別符,變量名的第一個字元必須是字母、$或“_”中的一種。變量名的第一個字元之後可以是字母、$、數字或“_”等,而且變量名最長可以有255個字元。另外,在Java中,變量名中字母大小寫的不同會被視為不同的變量。例如,M16與m16其實表示兩個不同的變量。
- 變量名不可以是關鍵字(Keyword)、保留字(Reserved Word)、運算符以及其他一些特殊字元,如int、class、+、-、*、/、@、#等。在Java語言中,關鍵字由具有明确意義的英文單詞組成,這些單詞被賦予了建構程式的功能,如聲明變量資料類型、程式的流程控制、表示布爾值等。Java語言中共有52個關鍵字,在使用時必須注意每一個關鍵字中的英文字母全為小寫。表2-6所示是按功能分類的Java關鍵字。
帶你讀《Java程式設計與計算思維》之二:認識資料處理與表達式第2章 認識資料處理與表達式
- 在同一個作用域(scope)内,變量名必須是獨一無二的;處于不同作用域時,變量名可以相同。注意:變量的作用域就是指變量的有效範圍。
雖然變量的命名從文法上講隻需要遵守上面的三個主要規則即可,但是在實際應用中,建議大家參考各個研發公司所制定的有關Java程式編寫的規範,因為如果大家都能遵守這些慣用的命名法,所編寫而成的程式就可以維持一緻性,無論是在程式的閱讀或維護上都較容易。下面列出編寫程式時建議的幾個重要規範。
- 不取無任何含義的變量名稱:在為變量命名時,還必須考慮一個重要原則,就是盡量使用有明确含義的名稱,避免無任何含義的變量名稱,如abc。盡量使用有代表意義的名稱,有明确含義的名稱可以突顯變量在程式中的用途,讓程式代碼易于了解、查錯、調試以及日後的維護。例如可以把存儲“姓名”的變量命名為name,把存儲“成績”的變量命名為score等。
- 注意變量名中字母的大小寫:在Java程式中有一個不成文的規則,通常變量名是以小寫英文字母作為開頭的,再接上一個大寫字母開頭且有含義的單詞,例如存儲“使用者密碼”的變量命名為userPassword。
表2-7列舉了不同的命名結果,并說明了這些命名是否合乎Java語言的命名規則。
在變量聲明方面,Java與其他的程式設計語言最大的不同在于它舍棄了定義“常數”的聲明,是以并不存在所謂的常數類型。不過,程式開發人員仍然可以使用Java關鍵字final來定義常數。final關鍵字的作用是強調在此關鍵字後面的各種對象不能再被覆寫、覆寫或重新定義。使用final關鍵字聲明常數的方式如下:
final 數值類型常數名稱 = 初始值;
final float PI = 3.1415926;
因為常數是一種固定、不會變動的數值,例如圓周率(PI)、光速(C)等,是以它的使用範圍通常包括整個程式。是以常數經常被聲明為類的成員,也就是所謂的成員資料,為了與普通變量有所區分,常數的命名大多是使用大寫英文字母。
下面的範例程式實作了相對論公式的計算。我們定義了一個常數C(光速)以及兩個變量m(品質)與e(能量),通過這個範例程式我們來了解變量與常數的聲明方式。
【範例程式:CH02_05】
01 // CH02_05.java,變量與常數的聲明
02 public class CH02_05 { //聲明常數C(光速)
03 final static double C = 2997924581.2;
04 public static void main(String args[]) {
05 //聲明變量e與m
06 int m;
07 double e;
08 //給變量指派
09 m = 10;
10 e = m * C * C;
11 //輸出到螢幕上
12 System.out.println("當品質為:" + m);
13 System.out.println("所釋放出的能量為:" + e);
14 }
15 }
程式的執行結果可參考圖2-8。
2.3 基本輸入與輸出功能
輸入(Input)與輸出(Output)是一個程式基本的功能。在Java中有各種負責資料輸入輸出的相關資料流(Data Stream)類,但是基礎的I/O操作莫過于使用System類中的out對象與in對象,它們各自都擁有一些與标準輸入(in對象)和輸出(out對象)相關的方法(Method)。
2.3.1 在螢幕上輸出資料
Java的标準輸出語句的聲明方式如下:
System.out.print(資料); //不會換行
System.out.println(資料); //會換行
- System.out:代表系統的标準輸出。
- println與print:它們的功能是将括号内的字元串列印輸出。差别在于print在輸出内容後不會換行,而println則會在輸出内容後自動換行。
- 資料的格式可以是任何類型,包括變量、常數、字元、字元串或對象等。
再看看下面的程式語句的輸出情況:
System.out.println("字元串A" + "字元串B"); //使用運算符“+”來執行字元串的串接運算
System.out.println (布爾值變量?變量A:變量B); //使用三元條件運算符來進行條件判斷
【範例程式:CH02_06】
01 //程式:CH02_06.java,基本輸出
02 public class CH02_06 {
03 public static void main(String args[]) { //聲明變量
04 String myStringA = "第一個字元串";
05 String myStringB = "第二個字元串";
06 String myStringC = "會串接在一起";
07 int myIntA = 3;
08 boolean myBoolean = true;
09 //在螢幕上輸出
10 System.out.print("[JAVA基本輸出練習]\n");
11 System.out.println("“真”的英文是" + myBoolean);
12 System.out.println(myStringA + myStringB);
13 System.out.println(myStringC);
14 System.out.println("1 + 2 = " + myIntA);
15 System.out.println("5 - 3 = " + (5 - myIntA));
16 }
17 }
程式的執行結果可參考圖2-9。
第10行:使用n轉義控制字元強制print()方法執行換行操作。
第10~15行:示範各種基本輸出使用模式。
2.3.2 從鍵盤輸入資料
在Java中,标準輸入可以使用System.in,并配合read()方法,使用方式如下:
System.in.read();
- System.in:代表系統的标準輸入。
- read():這個方法的功能是先從輸入流(例如鍵盤輸入的字元串)中讀取下一個位元組,再傳回這個字元的ASCII碼(0~255之間的整數)。
例如下面的程式語句:
System.out.println("請從鍵盤輸入一個字元");
char data = (char) System.in.read();
在這段程式中,因為read()會傳回整數類型,要對傳回的數值進行類型轉換的操作(将int類型轉換為char類型),是以必須在read方法前面加上“(char)”。另外,read()方法一次隻能讀取一個字元,由于在此程式中僅有一行調用read()方法的語句,是以在鍵盤上無論輸入多少個字元,它都隻會讀取第一個字元的ASCII值。
【範例程式:CH02_07】
01 //程式:CH02_07.java,基本輸入
02 import java.io.*;
03 public class CH02_07 {
04 private static char myData;
05 public static void main(String args[]) throws IOException {
06 System.out.print("[基本輸入練習]\n");
07 System.out.print("請輸入字元:");
08 //輸入字元
09 myData = (char)System.in.read();
10 System.out.println("輸入的字元為:" + myData);
11 }
12 }
程式的執行結果可參考圖2-10。
第04行:聲明一個字元變量myData,用以存儲使用者鍵盤所輸入的字元資料。
但問題是輸入的資料類型不可能隻限于單個字元,基于這個理由,我們不妨使用java.util.Scanner類,在這個類中可以通過Scanner對象來從外界擷取輸入的資料。有關Scanner對象的建立方式,必須使用new運算符,其聲明的文法如下:
java.util.Scanner input_obj=new java.util.Scanner(System.in);
當以上述語句建立好Scanner對象後,就可以調用該對象所提供的方法來擷取使用者從鍵盤輸入的資料。例如要輸入一整行字元串,Scanner對象提供了nextLine()方法;要擷取輸入的整數,Scanner對象提供了nextInt()方法;要擷取輸入的浮點數,Scanner對象提供了nextDouble()方法。下面為擷取各種資料類型輸入的語句:
java.util.Scanner input_obj=new java.util.Scanner(System.in);
System.out.print("請從鍵盤輸入字元串類型: ");
String StrVal =input_obj.nextLine();
System.out.println("您所輸入的字元串值為 "+StrVal);
System.out.print("請從鍵盤輸入整數類型: ");
int IntVal =input_obj.nextInt();
System.out.println("您所輸入的整數值為 "+IntVal);
System.out.print("請從鍵盤輸入浮點數類型: ");
double DoubleVal =input_obj.nextDouble();
System.out.println("您所輸入的浮點數為 "+DoubleVal);
2.4 資料類型的轉換
Java語言的資料類型定義很嚴謹,不允許資料類型之間随意轉換(Conversion),也就是說原本把變量聲明為int資料類型,如果給它賦予char類型的資料,在編譯時就會發生錯誤。資料轉換的方式有兩種:一種是“由小變大”;另一種是“由大變小”。
2.4.1 由小變大模式
如果“目的變量”和“源變量或資料”之間的類型不相同,在轉換時符合兩個條件,轉換後的源變量或資料類型就不會影響數值的精度。“由小變大”的轉換機制會“自動轉換”,而不會損失資料的精确度。下面列出轉換的機制:
double(雙精度浮點數)> float(浮點數)> long(長整數)> int(整數)> char(字元)> short(短整數)> byte(位元組)
- 轉換類型之間必須相容。例如short(短整數)可以和int(整數)互相轉換,但不可以和byte(位元組)互相轉換。
- “目的變量”的資料類型必須大于“源變量或資料”的資料類型,也就是以數值範圍較大的為主。例如short(短整數)可以和int(整數)互相轉換;int(整數)可以和long(長整數)互相轉換。
2.4.2 由大變小模式
“由大變小”的轉換機制需“指定轉換”,當“目的變量”的資料類型小于“源變量或資料”的資料類型時,使用的轉換文法如下:
(指定類型) 資料 | 變量; // 注意括号不可省略
所謂“指定類型”是指目的類型。“資料 | 變量”指的是源變量或資料。數值大範圍的資料類型轉換成數值小範圍的資料類型時,部分資料可能會被截去,即損失了精度。例如,聲明兩個整數變量分别為X和Y,并各賦予了初值,X=19、Y=4。如果進行除法運算“X/Y”,那麼運算的結果(Z)為4,但是如果希望計算結果的精确度能夠到小數點後面,結果的類型就不能使用“整數int”,正确的做法應該是采用“強制類型轉換”的方式來重新定義參與計算的變量值或數值:
Z=(float)X / (float)Y; // 先将X和Y原來聲明的整數類型強制轉變成浮點數類型
【範例程式:CH02_08】
01 //程式:CH02_08.java,資料類型的轉換
02 public class CH02_08 {
03 public static void main(String[ ] args) {
04 int i=10;
05 byte b=(byte) i;
06 byte b1=65;
07 char c=(char)b1;
08 System.out.println("i="+i);
09 System.out.println("b="+b);
10 System.out.println("b1="+b1);
11 System.out.println("c="+c);
12 }
13 }
程式的執行結果可參考圖2-11。
2.5 表達式與運算符
精确快速的計算能力是計算機最重要的能力之一,而這種能力是通過程式設計語言中各種五花八門的表達式來實作的。表達式(Expression)就像平常所用的數學公式一樣,是由運算符(Operator)與操作數(Operand)所組成的。以下是一個簡單的表達式:
d=a*b-123.4;
這個表達式中的d、a、b、123.4等常數或變量被稱為操作數,而=、*、-等運算符号被稱為運算符。Java語言的運算符除了基本的加、減、乘、除四則運算符之外,還有很多運算符,例如指派運算符(=)。表2-8列出了Java中基本的四則運算符以及其他用途的運算符。
表達式由操作數和運算符組成。操作數代表運算資料,運算符代表運算關系,例如算術運算符、關系運算符、邏輯運算符、移位運算符以及指派運算符等。任何運算都與操作數和運算符有關,如圖2-12所示。
2.5.1 算術運算符
算術運算符(Arithmetic Operator)的用途類似一般數學運算中的加(+)、減(-)、乘(×)和除(÷)四則運算,是經常使用的數學運算符。這些算術運算符在Java語言中的用法及功能與它們在傳統的數學中的用法及功能相同。不過,我們要注意的是加法運算符,在Java中,它除了可以執行數值加的運算,還具有“字元串串接”的功能。
(1)加、減、乘、除及求餘數
加、減、乘、除及求餘數運算符的用法可以參考表2-9。
其中,四則運算符和數學上的功能一模一樣,在此不多做介紹。而求餘數運算符“%”用于計算兩數相除後的餘數,這個運算要求參與運算的兩個操作數都必須是整數類型。
(2)遞增(Increment)與遞減(Decrement)運算
遞增“++”和遞減運算符“--”是對變量加1和減1的簡寫方式,這種運算隻适用于整數類型的變量,屬于一進制運算符(或稱為單目運算符),它們可增加程式代碼的簡潔性。要注意的是,遞增或遞減運算符在變量前後的位置不同,雖然都是對操作數執行加1或減1的運算,但是在表達式中的運算順序還是有差别的,遞增與遞減運算符可以分為字首(Prefix)和字尾(Postfix)兩種。使用方式和運算結果可參考表2-10。
(3)數值的正負數表示
正數預設不需要帶加号,但負數則要使用負号(即減法運算符)來表示。當負數進行減法運算時,為了避免運算符的混淆,最好以空格符或小括号“( )”隔開,例如:
int x=5; // 聲明變量x為int整數類型,并把它的初值設為5
x=x- -2; // 用空格符隔開,避免和遞減運算符相混淆
x=x-(-2); // 用小括号隔開
【範例程式:CH02_09】
01 /*檔案名:CH02_09.java
02 *說明:水果禮盒
03 */
04 public class CH02_09 {
05 public static void main(String args[]) {
06 int apple=15,banana=20;//聲明變量
07 System.out.print("(1).小明買了蘋果15個,香蕉20根,水果總共買了");
08 System.out.println((apple+banana)+"個");
09 System.out.print("(2).蘋果每個3元,香蕉每根1元,總共花費了");
10 System.out.println((apple*3+banana*1)+"元");
11 System.out.print("(3).将蘋果4個和香蕉3根裝成一盒,共可裝");
12 System.out.println((apple/4)+"盒");
13 System.out.println("(4).裝盒後蘋果剩下"+(apple%4)+"個,"+"香蕉剩下"+(20-apple/4*3)+"根");
14 }
15 }
程式的執行結果可參考圖2-13。
第06行:聲明變量apple(蘋果)和banana(香蕉),并分别設定初值為15和20。根據數量的資料類型,因而聲明這兩個變量為int類型。
第07~13行:示範簡單的算術運算。
2.5.2 關系運算符
關系運算符(Relational Operator)用于比較兩個操作數之間的關系,是大于(>)、小于(<)還是等于(= =),諸如此類的關系都可以用關系運算符來運算。運算的結果為布爾值,如果關系成立,就傳回真(true);如果關系不成立,就傳回假(false)。在Java中,關系比較運算符共有6種,如表2-11所示。
需要注意的是,一般數學上使用“≠”表示不等于,但是“≠”符号在編輯軟體中無法直接從鍵盤輸入,是以Java語言使用“!=”來代替“≠”表示不等于。另外,等于關系的表示方式在數學上一般使用一個等于符号(=)來表示,不過在Java語言中是以兩個等于符号(==)來表示的,是以讀者在編寫Java程式中要表達“不等于”和“等于”時要多加注意。
【範例程式:CH02_10】
01 /*檔案名:CH02_10.java
02 *說明:關系運算
03 */
04 public class CH02_10 {
05 public static void main(String args[]) {
06 System.out.print("15大于5 為"+(15>5)+"\n");
07 System.out.print("15小于5 為"+(15<5)+"\n");
08 System.out.print("15大于等于15 為"+(15>=15)+"\n");
09 System.out.print("15小于等于5 為"+(15<=5)+"\n");
10 System.out.print("15不等于5 為"+(15!=5)+"\n");
11 System.out.print("15等于5 為"+(15==5)+"\n");
12 }
13 }
程式的執行結果可參考圖2-14。
第06~11行:用關系運算符判斷兩個操作數之間的關系,判斷的結果為布爾(Boolean)資料類型。
程式代碼中使用“"n"”表示“換行”的意思。
2.5.3 邏輯運算符
邏輯運算符(Logical Operator)用于基本的邏輯運算,判斷的結果也是布爾資料類型,如果結果為真,其值為true(可用數字1表示);如果結果為假,其值為false(可用數字0表示)。&&和||運算符的運算順序是從左到右,而!運算符的運算順序是從右到左。
邏輯運算符在運用上可分為“布爾資料類型的邏輯運算”和“位的邏輯運算”。邏輯運算符用于判斷兩個關系運算符之間的關系,例如用于計算“a>0 && b>0”這類邏輯運算的結果。
(1)布爾資料類型的邏輯運算
Java中的邏輯運算符共有4種,如表2-12所示。
“!”代表“非”,是求反的意思。“&&”(AND)和“||”(OR)邏輯運算的真值表可參考表2-13和表2-14。
(2)位的邏輯運算
操作數在計算機記憶體中存儲的值實際上是以二進制方式存儲的。我們可以使用位運算符(Bitwise Operator)來對兩個整數操作數進行位與位之間的邏輯運算。我們将整數轉換成二進制數值時必須注意不同整數類型占用的存儲空間,byte類型的數值5占用一個位元組,因而轉換為二進制值為“00000101”,即8個二進制位(bit)。若是short類型,則占用兩個位元組,對應16個二進制位;int類型占用4個位元組,對應32個二進制位;long類型占用8個位元組,占用64個二進制位。
Java語言提供了4種位邏輯運算符,分别是&(AND,即“與”)、|(OR,即“或”)、^(XOR,即“異或”)與~(NOT,即“非”),如表2-15所示。
【範例程式:CH02_11】
01 /*檔案名:CH02_11.java
02 *說明:邏輯運算
03 */
04 public class CH02_11 {
05 public static void main(String args[]) {
06 int a=15,b=3;
07 System.out.println("(a>10)&&(b>5)的傳回值為 "+(a>10&&b>5));
08 System.out.println("(a>10)||(b>5)的傳回值為 "+(a>10||b>5));
09 System.out.println("(a>10)&(b>5)的傳回值為 "+(a>10&b>5));
10 System.out.println("(a>10)|(b>5)的傳回值為 "+(a>10|b>5));
11 System.out.println("(a>10)^(b>5)的傳回值為 "+(a>10^b>5));
12 System.out.println(" 15 & 3 的傳回值為 "+(a&b));
13 System.out.println(" 15 | 3 的傳回值為 "+(a|b));
14 System.out.println(" 15 ^ 3 的傳回值為 "+(a^b));
15 System.out.println(" ~3 的傳回值為"+(~b));
16 }
17 }
程式的執行結果可參考圖2-15。
第07~11行:布爾類型的邏輯運算。
第12~15行:位的邏輯運算。
2.5.4 移位運算符
移位運算符(Shift Operator)應用于整數類型,将整數轉換成二進制後,對二進制的各個位做向左或向右的移動。在Java語言中有兩種移位運算符,可參考表2-16的說明。
【範例程式:CH02_12】
01 /*檔案名:CH02_12.java
02 *說明:移位運算
03 */
04 public class CH02_12 {
05 public static void main(String args[]) {
06 System.out.println("5 << 2 的傳回值為 "+(5<<2));
07 System.out.println("-5 << 2 的傳回值為 "+(-5<<2));
08 System.out.println("5 >> 2的傳回值為 "+(5>>2));
09 System.out.println("-5 >> 2的傳回值為 "+(-5>>2));
10 }
11 }
程式的執行結果可參考圖2-16。
第06~09行:整數的移位運算。
2.5.5 指派運算符
指派運算符(Assignment Operator)由至少兩個操作數組成,主要作用是将等号“=”右方的值或者表達式的計算結果賦予等号左方的變量。由于是将“=”号右邊的值指派給“=”号左邊,是以“=”号的左邊必須是變量,而右邊則可以是變量、常數或表達式等。
初學者很容易将指派運算符“=”的作用和數學上的“等于”功能混淆,在程式設計語言中,“=”主要是指派的概念。以下是指派運算符的使用方式:
變量名稱 = 要賦予的值或表達式;
a= a + 5; /* 将a值加5後指派給變量a */
c ='A'; /* 将字元'A'指派給變量c */
a=a+5在數學上根本不成立,不過在Java的世界中,我們可以這樣解讀:當聲明變量之後,在記憶體中已經給這個變量配置設定了記憶體空間,在後續使用中就要使用指派運算符來給該變量指派。Java語言的指派運算符除了一次給一個變量指派外,還能夠把同一個數值同時指派給多個變量,例如:
int x,y,z;
x=y=z=200; /* 把一個值同時賦給不同變量 */
在Java中還有一種複合指派運算符,是由指派運算符與其他運算符組合而成的。先決條件是指派号“=”右邊的源操作數必須有一個和左邊接收指派數值的操作數相同,如果一個表達式含有多個複合指派運算符,運算過程必須從右邊開始,逐漸進行到左邊。
例如以“A += B;”語句來說,它就是語句“A=A+B;”的精簡寫法,也就是先執行A+B的計算,接着将計算結果指派給變量A。這類運算符的說明及使用文法如表2-17所示。
下面的範例程式用于說明複合指派運算符的使用方式。要特别注意的是,在運算過程中,運算的順序是從指派号的右邊開始的,而後逐漸進行到左邊。例如,複合指派運算符在多重表達式中的使用:
a+=a+=b+=b%=4;
這個表達式的實際運算順序和運算過程如下:
b =b%4
b=b+b;
a=a+b;
a=a+a;
【範例程式:CH02_13】
01 /*檔案名:CH02_13.java
02 *說明:指派運算
03 */
04 public class CH02_13 {
05 public static void main(String args[]) {
06 int A=5;
07 System.out.println("A=5 ");
08 A+=3+2;
09 System.out.println("A+= 3+2 的值為 "+(A));
10 A=5;
11 A-=5-4;
12 System.out.println("A-= 5-4 的值為 "+(A));
13 A=5;
14 A*=2*3;
15 System.out.println("A*= 2*3 的值為 "+(A));
16 A=5;
17 A/=10/5+3;
18 System.out.println("A/= 10/5+3 的值為 "+(A));
19 A=5;
20 A%=15%4;
21 System.out.println("A%= 15%4的值為 "+(A));
22 A=5;
23 A &=5-3;
24 System.out.println("A&= 5-3 的值為 "+(A));
25 A=5;
26 A|=2;
27 System.out.println("A|= 2 的值為 "+(A));
28 A=5;
29 A^=2+1;
30 System.out.println("A^= 2+1 的值為 "+(A));
31 }
32 }
程式的執行結果可參考圖2-17。
第06~30行:變量A的指派運算。
2.5.6 運算符的優先級
一個表達式中往往包含多個運算符,這些運算符執行的先後順序如何呢?這時就需要按照運算符的優先級來建立運算規則。當表達式中使用多個運算符時,例如z=x+3y,就必須按照運算符的優先級來進行運算。按照數學基本運算中“先乘除後加減”的規則,這個表達式會先執行3y的運算,把運算的結果與x相加,再将相加的結果指派給z,最後得到這個表達式的最終運算結果。在Java中,在處理含有多個運算符的表達式時,同樣必須遵守一些規則與步驟,說明如下:
(1)當遇到一個表達式時,先區分運算符與操作數。
(2)按照運算符的優先級進行整理。
(3)将各個運算符根據其結合順序進行運算。
在進行包含多種運算符的運算時,必須先了解各種運算符的“優先級”和“結合律”。假如表達式中有多個運算符,那麼各個運算符要按照既定的順序完成運算,這裡所說的順序就是運算符“優先運算的順序”。表達式中常見的括号(如“( )”)具有最高的優先級,即括号内的運算優先級高于括号外的運算優先級。表2-18列出了Java中各種運算符的優先級。
表2-18中所列的優先級,1代表最高優先級,15代表最低優先級。“結合律”指在表達式中遇到同等級優先級時的運算規定,如“3+2-1”,加号“+”和減号“-”同屬于優先級4,根據結合律,順序是從左到右,先從最左邊執行“3+2”的運算後,再往右執行減“-1”的運算。程式設計人員應該熟悉各個運算符的優先級和結合律,這樣在編寫程式時才不至于出現這類錯誤或不合理的問題。
2.6 進階應用練習執行個體
本章主要讨論了Java語言的基本資料處理,包括變量與常數、各種資料類型、類型轉換和運算符等。另外,如果可以靈活使用各種資料類型,再搭配簡易的輸出指令和運算符,就可以編寫出許多實用的程式。
2.6.1 多重邏輯運算符的應用
我們知道邏輯運算符運用于條件判斷表達式來控制程式執行的流程,而一個條件判斷表達式中可以使用多個邏輯運算符。不過,當連續使用邏輯運算符時,它的計算順序為從左到右進行。以下程式中聲明了a、b和c三個整數變量,并賦予了初值,請判斷以下兩個表達式結果的真假值(布爾類型的結果,true或者false):
a<b && b<c || c<a
!(a<b) && b<c || c<a
【綜合練習】多重邏輯運算符的應用與範例
01 // 多重邏輯運算符的應用與範例
02 public class WORK02_01 {
03 public static void main (String args[] ) {
04 int a=7,b=8,c=9; /*聲明a、b和c三個整數變量,并賦初值*/
05 System.out.println("a<b && b<c || c<a = "+(a<b && b<c || c<a));
06 /* 先計算“a<b && b<c”,再将結果與“c<a”進行OR的運算 */
07 System.out.println("!(a<b) && b<c || c<a = "+(!(a<b) && b<c || c<a));
08 }
09 }
程式的執行結果可參考圖2-18。
2.6.2 位邏輯運算符的運算練習
請大家運用位邏輯運算符對兩個整數12與7進行位與位之間的AND、OR、XOR位邏輯運算,并顯示出運算結果。
【綜合練習】位邏輯運算符的應用與範例
01 // 位邏輯運算符的應用與範例
02 public class WORK02_02 {
03 public static void main (String args[]) {
04 int bit_test=12;/* 聲明整數變量并賦初值 (00001100) */
05 int bit_test1=7;/* 聲明整數變量并賦初值 (00000111)*/
06 System.out.println("bit_test="+bit_test+" bit_test1= "+bit_test1);
07 System.out.println("-----------------------------------------");
08 /* 執行 AND、OR、XOR 位邏輯運算 */
09 System.out.println("執行 AND 運算的結果:"+(bit_test & bit_test1));
10 System.out.println("執行 OR 運算的結果:"+(bit_test | bit_test1));
11 System.out.println("執行 XOR 運算的結果:"+(bit_test ^ bit_test1));
12 }
13 }
程式的執行結果可參考圖2-19。
2.6.3 自動類型轉換與強制類型轉換的比較
我們知道強制類型轉換可以用來彌補自動類型轉換無法處理的情況。例如下面的情況:
int i=100, j=3;
float Result;
Result= i /j;
這時自動類型轉換會将i/j的結果(整數值33)轉換成float類型,再指派給Result變量,得到33.000000,而i/j小數點後面的部分完全被舍棄了,是以無法得到精确的結果值。如果我們要擷取小數部分的數值,請試着在上述程式代碼中增加強制類型轉換的功能。
除了由編譯器自行轉換的自動類型轉換之外,Java語言還允許使用者強制轉換資料類型。例如,如果想讓兩個整數相除得到更精确的結果,那麼可以用強制類型轉換,即将兩個整數轉換成浮點數類型。要在表達式中強制轉換資料類型,采用如下文法:
(強制轉換類型名稱) 表達式或變量;
例如以下程式片段:
int a,b,avg;
avg=(float)(a+b)/2;/* 将a+b的結果值強制轉換為浮點數類型 */
注意,上述程式語句中包含轉換類型名稱的小括号是絕對不可以省略的,否則計算結果得到的浮點數在被自動類型轉換為整數時,小數部分會被直接舍棄。另外,在指派運算符“=”左邊的變量不能進行強制資料類型轉換,例如:
(float)avg=(a+b)/2; /* 不合法的程式語句 */
【綜合練習】強制類型轉換練習
01 // 自動類型轉換與強制類型轉換的比較
02 public class WORK02_03 {
03 public static void main (String args[]) {
04 int i=100, j=3; /* 聲明整數變量 i 與 j,并賦初值 */
05 float Result; /* 聲明浮點數變量 Result */
06 System.out.println("自動類型轉換的執行結果為:");
07 Result=i/j; /* 自動類型轉換 */
08 System.out.println("Result=i/j="+i+"/"+j+"="+Result);
09 System.out.println("--------------------------------------");
10 System.out.println("強制類型轉換的執行結果為:");
11 Result=(float) i / j; /* 強制類型轉換 */
12 System.out.println("Result=(float)i/(float)j="+i+"/"+j+"="+Result);
13 System.out.println("--------------------------------------");
14 }
15 }
程式的執行結果可參考圖2-20。
課後習題
一、填空題
1. 是指“變量在使用之前,必須聲明其資料類型,我們可以任意存取這個變量的值,但是變量所聲明的資料類型不可以随意變更”。
2.Java的資料類型可以分成 與 。
3. 在程式設計語言中代表資料存儲的記憶體空間。
4.布爾資料類型資料結果的表示隻有 和 兩種。
5.基本資料類型按照使用性質的不同,可分成 、 、 及 4種。
6.如果字母B的Unicode值為42,它的Java字元資料表示值為 。
7.Java定義的整數類型包含 、 、 和 。
8.聲明語句的文法可分成 與 兩部分。
9.在字元前加上反斜杠“”來通知編譯器将後面的字元當成一個特殊字元,就是所謂的 。
10.表達式是由 和 組成的。
11. 是用來表示Unicode碼格式的,不同的字元有不同的資料表示值。
12.當用負數進行減法運算時,為了避免分辨運算符造成的混淆,最好以 或 隔開。
二、問答與實踐題
1.說明 Java中變量的命名規則有哪些注意事項。
2.表2-19中不正确的變量命名違背了哪些原則?
3.遞增(++)和遞減(--)運算方式可分成哪兩種?
4.判斷下列命名中哪些是合法的命名、哪些是不合法的命名?
A.is_Tim
B.is_TimChen_Boy_NICE_man
C.Java SE 11
D.Java_11
E.#Tom
F.aAbBcC
G.1.5_J2SE
5.下列程式代碼是否有錯,如果有錯,請說明原因。
01 public class EX02_05 {
02 public static void main(String args[ ]) {
03 int number1=15:number2=8; //聲明兩個變量,并賦初值
04 System.out.print("兩個數相加的結果為:");
05 System.out.println(number1+number2);
06 }
07 }
6.下列程式代碼是否有錯,如果有錯,請說明原因。
01 public class EX02_06 {
02 public static void main(String args[ ]) {
03 int a,b;
04 float c=(a+b);
05 System.out.println("計算結果= "+c);
06 }
07 }
7.請編寫Java程式來實作“sum=12; t=2;sum+=t”這段程式代碼,這段程式執行後,觀察sum的值是多少,t的值又是多少。
8.請程式設計實作“int a=11,b=21,c=12,d=31;boolean ans=(c>a)&&(b9.請解釋什麼是操作數和運算符,并列舉各種運算符。
10.試舉出至少10個關鍵字。
11.舉例說明資料類型的自動類型轉換。
12.請比較下列運算符的優先級。
① 括号:( ) 、 [ ]
② 條件選擇運算符:?:
③ 指派運算:=
13.請設計一個Java程式,可用來計算圓的面積及其周長。
14.請設計一個Java程式,可用來計算梯形的面積。
15.改寫第14題,不過此次梯形的上底、下底和高可由使用者自行輸入,并計算梯形面積。