第二章 基本程式設計
簡介 本章的重點在學習基本的程式設計技巧,用來解決問題。 第一章介紹了如何建立、編譯,以及執行非常基本的Java程式。接下來將學習如何藉由撰寫程式來解決問題。經由這些問題,您將接觸基本的資料型態,變數、常數、運算子、運算式、輸入及輸出,學習基本的程式設計。
本章綱要 撰寫Java程式以執行簡單計算(§2.2) 利用Scanner類別從console取得輸入資訊(§2.3) 利用識別字(identifiers)命名變數、常數、方法及類別(§2.4) 使用變數儲存資料(§§2.5-2.6) 撰寫帶有指定敘述(assignment statements)與指定運算式(assignment expressions)的程式(§2.6) 使用常數儲存永久資料(§2.7) 根據命名慣例,為類別、方法、變數及常數命名(§2.8) Java數值原始資料型態:byte、short、int、long、float及double(§2.9.1) 使用運算子 +、-、*、/ 及 % 執行運算(§2.9.2) 使用Math.pow(a, b)執行指數運算(§2.9.3) 以科學記號表示整數字面常數、浮點字面常數及字面常數(§2.10) 撰寫與解析數值運算式(§2.11) 利用System.currentTimeMillis() 取得目前的系統時間(§2.12) 使用增強指定運算子(augmented assignment operators)(§2.13) 辨別後繼遞增遞減與前置遞增遞減的不同(§2.14) 型態轉換(§2.15) 說明軟體開發流程,並將其應用在開發貸款繳付程式上(§2.16) 使用char型態表示字元(§2.17) 使用String型態表示字串(§2.18) 利用JOptionPane輸入對話方塊,取得輸入資訊(§2.19)
撰寫一支簡單的程式 範例程式 2.1 ComputingArea.java 此程式用以計算圓形的面積. ComputeArea Run 重要注意事項:(1)要啟用按鈕,你必須下載整個的幻 燈片檔案slide.zip,並將檔案解壓縮後存成文件目錄( 例如,c:\幻燈片)。 (2)您必須事先下載JDK並安 奘JDK’s bin directory在你的環境路徑(例如:c:\Program Files\java\jdk1.7.0\bin in your environment path)。 (3) 如果您使用的是Office 2010,確定PowerPoint2010.doc 和這份ppt檔案至於同一資料夾內。 Run
追蹤程式的執行 animation 為變數radius劃分記憶體 public class ComputeArea { /** Main method */ public static void main(String[] args) { double radius; double area; // Assign a radius radius = 20; // Compute area area = radius * radius * 3.14159; // Display results System.out.println("The area for the circle of radius " + radius + " is " + area); } radius no value
追蹤程式的執行 animation public class ComputeArea { /** Main method */ memory public static void main(String[] args) { double radius; double area; // Assign a radius radius = 20; // Compute area area = radius * radius * 3.14159; // Display results System.out.println("The area for the circle of radius " + radius + " is " + area); } memory radius no value area no value 為變數area劃分記憶體
追蹤程式的執行 animation 將20指定給變數radius public class ComputeArea { /** Main method */ public static void main(String[] args) { double radius; double area; // Assign a radius radius = 20; // Compute area area = radius * radius * 3.14159; // Display results System.out.println("The area for the circle of radius " + radius + " is " + area); } radius 20 area no value
追蹤程式的執行 20 1256.636 animation public class ComputeArea { /** Main method */ public static void main(String[] args) { double radius; double area; // Assign a radius radius = 20; // Compute area area = radius * radius * 3.14159; // Display results System.out.println("The area for the circle of radius " + radius + " is " + area); } memory radius 20 area 1256.636 計算圓面積並將結果指定給變數 area
追蹤程式的執行 animation public class ComputeArea { /** Main method */ public static void main(String[] args) { double radius; double area; // Assign a radius radius = 20; // Compute area area = radius * radius * 3.14159; // Display results System.out.println("The area for the circle of radius " + radius + " is " + area); } memory radius 20 area 1256.636 將結果顯示於輸出裝置上
ComputeAreaWithConsoleInput 從控制台讀取輸入資訊 1.建立一個Scanner型態的物件 Scanner input = new Scanner(System.in); 2.藉由呼叫方法 next(), nextByte(), nextShort(), nextInt(), nextLong(), nextFloat(), nextDouble(), or nextBoolean() 讀取 string, byte, short, int, long, float, double, or boolean 。舉例來說: System.out.print("Enter a double value: "); double d = input.nextDouble(); ComputeAreaWithConsoleInput ComputeAverage Run Run
識別字 識別字是由字母、數字、底線(_),以及錢字符號($)所組成的字元序列 識別字必須以字母、底線(_)或錢字符號($)起頭。不能以數字當開頭字元 識別字不能是保留字 ((可參考附錄A,檢視保留字清單。) 識別字不能是true、false或null 識別字的長度不限
變數 // Compute the first area radius = 1.0; area = radius * radius * 3.14159; System.out.println("The area is “ + area + " for radius "+radius); // Compute the second area radius = 2.0;
變數宣告 int x; // Declare x to be an // integer variable; double radius; // Declare radius to // be a double variable; char a; // Declare a to be a // character variable;
指定敘述 x = 1; // Assign 1 to x; radius = 1.0; // Assign 1.0 to radius; a = 'A'; // Assign 'A' to a;
同時宣告與初始化 int x = 1; double d = 1.4;
具名常數 final datatype CONSTANTNAME = VALUE; final double PI = 3.14159; final int SIZE = 3;
命名慣例 以描述性的命名方式為常數取名稱 變數與方法的命名: 對變數及方法使用小寫。如果名稱帶有數個單詞,可將它們合成一個名稱,將第一個單詞小寫,之後每個單詞的頭一個字母大寫,比方說,變數raidus、area及方法computeArea。
命名慣例 類別的命名: 常數的命名: 將類別名稱的每個單詞的頭一個字母大寫,比方說,類別ComputeArea。 常數名稱的每個字元都大寫,字詞間用底限做連接,比方說,常數PI及MAX_VALUE。
數值資料型態 名稱 範圍 儲存大小 byte -27 to 27-1(-128 to 127) 8-bit signed byte type byte -27 to 27-1(-128 to 127) 8-bit signed byte type short -215 to 215-1(-32768 to 32767) 16-bit signed short type int -231 to 231-1(-2147483648 to 2147483647) 32-bit int type long -263 to 263-1 (i.e., - 9223372036854775807 to 9223372036854775808) 64-bit signed long type float 負數範圍: -3.4028235E+38 ~ -1.4E-45 正數範圍: 1.4E-45 to 3.4028235E+38 32-bit IEEE 754 float type doubl e 負數範圍: - 1.7976931348623157E+308 ~ -4.9E-324 正數範圍: 4.9E-324 ~ 1.7976931348623157E+308 64-bit IEEE 754 double type
數值運算子 名稱 含意 範例 結果 + 加法 34 + 1 35 - 減法 34.0 – 0.1 33.9 * 乘法 300 * 30 9000 / 除法 1.0 / 2.0 0.5 % 餘數 20 %3 2
整數除法 +, -, *, /, % 5 / 2結果會為2 5.0 / 2結果會是2.5 5 % 2 結果會是 1 ( 即5除以2的餘數 )
餘數運算子 餘數在程式設計中很有用。例如,偶數 % 2的結果永遠是0,基數 % 2的結果則永遠是1。因此便可利用這個特性來判斷某數值是偶數還是基數。假設今天是禮拜六,七天之後還會是禮拜六。假設您跟朋友相約10天後見面。10天後是哪一天呢?可藉由以下運算式得知見面那天將是禮拜二:
範例程式2.4 DisplayTime.java 撰寫一個程式,以秒表示的總時間長,取得分鐘數及剩餘的秒數。 DisplayTime Run
註釋 涉及浮點數的計算都會做近似處理(approximation),因為這些數值並不會完全準確地被儲存。 比方說,會顯示0.5000000000000001,而不是0.5,而 則會顯示0.09999999999999998,而不是0.1。 整數則會精準地被儲存。因此,整數運算的結果會是精確的整數值。
指數運算 System.out.println(Math.pow(2, 3)); // Displays 8.0
字面常數 int i = 34; long x = 1000000; double d = 5.0; 字面常數(number literals)為一個直接出現於程式中的常數值(constant value)。 舉個例子,34和0.305為以下敘述的字面常數: int i = 34; long x = 1000000; double d = 5.0;
整數字面常數 整數字面常數(integer literal)可指定給整數變數,只要這個變數可容納此常數即可。如果字面常數過大,導致變數無法儲存,編譯器便會產生錯誤訊息。舉個例子,byte b = 1000這個敘述便會產生編譯錯誤,因為byte型態的變數無法容納1000這個數值。(byte型態可儲存的數值範圍為 -128到127。) 整數字面常數被指定為int型態,其數值範圍為 -231(-2147483648)到231-- 1(2147483647)。要將整數字面常數標記為long型態的話,可在數值最後加上一個L或l字母。最好使用L,因為小寫l容易跟數字1搞混。
浮點數字面常數 浮點數字面常數(floating-point literals)帶有小數點。預設情況下,浮點數字面常數會被當作double型態。比方說,5.0會被當作double數值,而不是float。您可以藉由在數值最後加上字母f或F,將數值設定為float型態,也可以加上字母d或D,將數值設為double型態。比方說,我們可以使用100.2f或100.2F作為一個float數值,可以使用100.2d或100.2D作為一個double數值。
科學記號 浮點數字面常數能以科學記號(scientific notation)的形式( a x 10b )來表示。比方說,123.456以科學記號來表示即為1.23456 x 102,0.0123456則會以1.23456 x 10-2來表示。這裡的E(或e)代表指數,可以是大寫也可以是小寫。
算術運算式 可翻譯成如下的Java運算式: (3+4*x)/5 – 10*(y-5)*(a+b+c)/x + 9*(4/x + (9+x)/y)
如何解析運算式 雖然說Java內部有自己解析運算式(evaluate an expression)的方法,但Java運算式的解析結果,與相對應的算術運算式仍是相同的。因此,您可以放心地使用算術規則來解析Java運算式。
範例程式2.5 FahrenheirToCelsius.java 利用攝氏 =(5/9)(華氏 – 32)的公式,撰寫一個將華氏度數轉換成攝氏度數的程式: 註釋: 必須得寫出部分 celsius = (5.0 / 9) * (fahrenheit – 32) FahrenheitToCelsius Run
範例程式2.6 ShowCurrentTime.java 撰寫一個以格林威治標準時間(GMT)為基準所顯示的目前時間,顯示的格式為小時:分鐘:秒數,例如13:19:8。 System類別裡的currentTimeMillis方法會回傳目前的時間,目前的時間是從GMT 1970年1月1號的00:00:00開始計算(1970年正是UNIX作業系統正式發表的時間),所經過的毫秒數,如下圖所示。 ShowCurrentTime Run
增強指定運算子 運算子 名稱 範例 相當於 += 加法指定 i += 8 i = i + 8 -= 減法指定 i -= 8 *= 乘法指定 i *= 8 i = i * 8 /= 除法指定 i /= 8 i = i / 8 %= 餘數指定 i %= 8 i = i % 8
遞增及遞減運算子 運算子 名稱 說明 範例 ++var 前置遞增 將var遞增1,並於程式敘述 中使用新的var值 int j = ++i; // j is 2, i is 2 var++ 後繼遞增 將var遞增1,但於程式敘述 中使用原本的var值 int j = i++; // j is 1, i is 2 --var 前置遞減 將var遞減1,並於程式敘 述中使用新的var值 int j = --i; // j is 0, i is 0 var-- 後繼遞減 將var遞減1,但於程式敘述 int j = i--; // j is 1, i is 0
遞增及遞減運算子
遞增及遞減運算子 使用遞增與遞減運算子能讓運算式更精簡,但也相對會讓程式碼變得更複雜與難以閱讀。在需要修改多項變數,或對同個變數做多次修改的運算式上,避免使用這類運算子,例如 int k = ++i + i。
指定敘述及指定運算式 於Java 2 之前,所有的運算式皆可做敘述使用。於Java 2後,只有以下的運算式型態可以作為敘述使用: variable op= expression; // Where op is +, -, *, /, or % ++variable; variable++; --variable; variable--;
數字型態轉換 比方說,以下敘述: byte i = 100; long k = i * 3 + 4; double d = i * 3.1 + k / 2;
型態轉換規則 如果二元運算涉及兩種不同型態的數值運算,Java會 依據下列規則自動地將數值做轉換: 1. 兩數值中如有一方資料型態為double,則另一數值自動轉換為double型態。 2. 此外,兩數值中如有一方資料型態為folat,則另一數值自動轉換為float型態。 3. 此外,兩數值中如有一方資料型態為long,則另依數值自動轉換為long型態。 4. 此外,兩數值皆轉換為int型態。
型態轉換 隱藏轉換 double d = 3; (加寬型態) 直接轉換 int i = (int)3.0; (窄化型態) 為何錯誤? int x = 5 / 2.0;
範例程式2.7 SalesTax.java 撰寫一個計算銷售稅至小數點後兩位的程式。 SalesTax Run
轉換型態於增強運算式 在Java裡,x1 op= x2 的增強運算式會被實作成x1 =(T)(x1 op x2),這裡的T為x1的型態。因此,以下程式內容是正確的。 int sum = 0; sum += 4.5; // sum becomes 4 after this statement sum += 4.5 is equivalent to sum = (int)(sum + 4.5).
軟體開發流程
需求規格
系統分析
系統設計
IPO
實作
測試
部署
維護
範例程式2.8 ComputeLoan.java 撰寫一個容許使用者輸入利率、貸款額,以及償還的總年數,並計算出月支付額及總支付額的程式。 Run
字元資料型態 char letter = 'A'; (ASCII) char numChar = '4'; (ASCII) 四個十六進位數字 char letter = 'A'; (ASCII) char numChar = '4'; (ASCII) char letter = '\u0041'; (Unicode) char numChar = '\u0034'; (Unicode) 註釋:遞增與遞減運算子也可被用在char變數上,以取得下一個或前一個Unicode字元。比方說,以下敘述會顯示字元b。 char ch = 'a'; System.out.println(++ch);
萬國碼 Java支援萬國碼(Unicode),由Unicode協會所建立的編碼方案,支援世界上各種書寫語言的互換、處理,以及顯示。16位元的Unicode佔據兩個bytes,以四個十六進位數字,前面再加上 \u符號來表示,範圍介於 \u0000到 \uFFFF,所以, Unicode 可以表示的65535 + 1 個字元。 此三姑希臘字母的Unicode分別為 \u03b1 \u03b2 \u03b3 。 以Unicode表示的希臘字母αβγ
範例程式2.9 DisplayUnicode.java 撰寫一個顯示兩個中文字元及三個希臘字母的程式。 DisplayUnicode Run
跳脫字元 跳脫字元 名稱 Unicode Code 十進位數值 \b Backspace \u0008 8 \t Tab \u0009 9 換行且游標移到行首 \u000A 10 \f 換頁 \u000C 12 \r 游標移到行首 \u000D 13 \\ 反斜線 \u005C 92 \" 雙引號 \u0022 34
附錄 B: ASCII 字元對照表 ASCII 字元集之十進位對照表( Unicode : \u0000 ~ \u007f )
附錄 B: ASCII 字元對照表 ASCII 字元集之十六進位對照表( Unicode : \u0000 ~ \u007f )
char與數字型態之間的轉換 int i = 'a'; // Same as int i = (int)'a'; char c = 97; // Same as char c = (char)97;
範例程式2.10 ComputeChange.java 此程式讓使用者輸入double型態的總金額,以美元與分來表示,接著輸出依序對等的美元,25分(quarters)、10分(dimes)、5分(nickels),以及1分(pennies)的組合,以使用最少的硬幣來計算。 ComputeChange Run
初始化變數remainingAmount 追蹤程式的執行 假設總金額為 11.56 int remainingAmount = (int)(amount * 100); // Find the number of one dollars int numberOfOneDollars = remainingAmount / 100; remainingAmount = remainingAmount % 100; // Find the number of quarters in the remaining amount int numberOfQuarters = remainingAmount / 25; remainingAmount = remainingAmount % 25; // Find the number of dimes in the remaining amount int numberOfDimes = remainingAmount / 10; remainingAmount = remainingAmount % 10; // Find the number of nickels in the remaining amount int numberOfNickels = remainingAmount / 5; remainingAmount = remainingAmount % 5; // Find the number of pennies in the remaining amount int numberOfPennies = remainingAmount; remainingAmount 1156 初始化變數remainingAmount
將11指定給變數numberOfOneDollars animation 追蹤程式的執行 假設總金額為 11.56 int remainingAmount = (int)(amount * 100); // Find the number of one dollars int numberOfOneDollars = remainingAmount / 100; remainingAmount = remainingAmount % 100; // Find the number of quarters in the remaining amount int numberOfQuarters = remainingAmount / 25; remainingAmount = remainingAmount % 25; // Find the number of dimes in the remaining amount int numberOfDimes = remainingAmount / 10; remainingAmount = remainingAmount % 10; // Find the number of nickels in the remaining amount int numberOfNickels = remainingAmount / 5; remainingAmount = remainingAmount % 5; // Find the number of pennies in the remaining amount int numberOfPennies = remainingAmount; remainingAmount 1156 numberOfOneDollars 11 將11指定給變數numberOfOneDollars
調整變數remainingAmount所儲存的餘額 animation 追蹤程式的執行 假設總金額為 11.56 int remainingAmount = (int)(amount * 100); // Find the number of one dollars int numberOfOneDollars = remainingAmount / 100; remainingAmount = remainingAmount % 100; // Find the number of quarters in the remaining amount int numberOfQuarters = remainingAmount / 25; remainingAmount = remainingAmount % 25; // Find the number of dimes in the remaining amount int numberOfDimes = remainingAmount / 10; remainingAmount = remainingAmount % 10; // Find the number of nickels in the remaining amount int numberOfNickels = remainingAmount / 5; remainingAmount = remainingAmount % 5; // Find the number of pennies in the remaining amount int numberOfPennies = remainingAmount; remainingAmount 56 numberOfOneDollars 11 調整變數remainingAmount所儲存的餘額
將2指定給變數numberOfOneQuarters animation 追蹤程式的執行 假設總金額為 11.56 int remainingAmount = (int)(amount * 100); // Find the number of one dollars int numberOfOneDollars = remainingAmount / 100; remainingAmount = remainingAmount % 100; // Find the number of quarters in the remaining amount int numberOfQuarters = remainingAmount / 25; remainingAmount = remainingAmount % 25; // Find the number of dimes in the remaining amount int numberOfDimes = remainingAmount / 10; remainingAmount = remainingAmount % 10; // Find the number of nickels in the remaining amount int numberOfNickels = remainingAmount / 5; remainingAmount = remainingAmount % 5; // Find the number of pennies in the remaining amount int numberOfPennies = remainingAmount; remainingAmount 56 numberOfOneDollars 11 numberOfOneQuarters 2 將2指定給變數numberOfOneQuarters
調整變數remainingAmount所儲存的餘額 animation 追蹤程式的執行 假設總金額為 11.56 int remainingAmount = (int)(amount * 100); // Find the number of one dollars int numberOfOneDollars = remainingAmount / 100; remainingAmount = remainingAmount % 100; // Find the number of quarters in the remaining amount int numberOfQuarters = remainingAmount / 25; remainingAmount = remainingAmount % 25; // Find the number of dimes in the remaining amount int numberOfDimes = remainingAmount / 10; remainingAmount = remainingAmount % 10; // Find the number of nickels in the remaining amount int numberOfNickels = remainingAmount / 5; remainingAmount = remainingAmount % 5; // Find the number of pennies in the remaining amount int numberOfPennies = remainingAmount; remainingAmount 6 numberOfOneDollars 11 numberOfQuarters 2 調整變數remainingAmount所儲存的餘額
String型態 char型態代表單一字元。要表示字元序列組成的字串,得使用稱作String的資料型態。比方說: String message = "Welcome to Java"; String是Java程式庫裡預先定義的類別,就跟類別System、JOptionPane一樣。String型態並非原始型態。它被稱做參考型態(reference type)。任何Java類別都可被用來當作變數的參考型態。參考型態將在第8章 ”物件與類別 “ 做完整的討論。目前您只需要知道如何宣告String變數,如何將字串指定給變數,以及如何連結字串。 S
連結字串 // Three strings are concatenated String message = "Welcome " + "to " + "Java"; // String Chapter is concatenated with number 2 String s = "Chapter" + 2; // s becomes Chapter2 // String Supplement is concatenated with character B String s1 = "Supplement" + 'B'; // s1 becomes SupplementB
除錯 邏輯錯誤又稱為 bugs,而找尋與改正錯誤的過程則稱為偵錯( debugging )。常見的偵錯方法之一,便是利用方法的組合來減少錯誤部分的程式。你也可以利用追蹤程式(tracing a program) 的方式來偵錯( 比方說,詳細閱讀程式來找到bugs ),或者你也可以利用輸出來檢視程式中變數或執行的結果變化,然而,這些方法僅適用於簡易的程式,如果程式龐大複雜,那麼最有效率的偵錯方式便是利用除錯工具(debugger utility)。
偵錯器 偵錯器 ( debugger ) 為專門用來偵錯的程式。 你可以利用偵錯器做到: 一次執行一個敘述 追蹤方法 設置中斷點 顯示變量 顯示 call stack. 修改變量
JOptionPane 輸入 本書使用兩種方式來接收輸入資訊。 使用 Scanner class (console input) 使用 JOptionPane input dialogs
從輸入對話方塊內取得輸入資訊 String input = JOptionPane.showInputDialog( "Enter an input");
從輸入對話方塊內取得輸入資訊 String string = JOptionPane.showInputDialog( null, “Prompting Message”, “Dialog Title”, JOptionPane.QUESTION_MESSAGE);
兩種導入方法的方式 呼叫showInputDialog方法有多種方式。目前您只需要知道其中兩種。第一種呼叫方式如下: x為提示訊息的字串。 String string = JOptionPane.showInputDialog(null, x, y, JOptionPane.QUESTION_MESSAGE); x為提示訊息的字串。 另一種呼叫方式如下: JOptionPane.showInputDialog(x); x為提示訊息的字串,y為輸入對話方塊的標題字串。
將String轉換為int int intValue = Integer.parseInt(intString); 輸入對話方塊所回傳的輸入資訊為一個字串。如果輸入資訊為一數值123,此方法就會回傳"123"。因此,我們必須將此字串轉換為數字,以取得原本輸入的數值資訊。 要將字串轉換為int值,得使用Integer.parseInt方法,如下: int intValue = Integer.parseInt(intString); 這裡的intString為一個數值字串,比方說123。
將String轉換為double double doubleValue =Double.parseDouble(doubleString); 要將字串轉換成double值,就得使用Double.parseDouble方法,如下: double doubleValue =Double.parseDouble(doubleString); where doubleString is a numeric string such as “123.45”.
範例程式2.11 ComputeLoanUsingInputDialog.java 重新撰寫範例程式2.8 ComputeLoan.java的內容,使其從輸入對話方塊,而不是console內讀取輸入資訊。 ComputeLoanUsingInputDialog Run
Companion Website NetBeans 的偵錯 詳見補充 II.E,學習有效率的使用 NetBeans。
Companion Website Eclipse的偵錯 詳見補充 II.G,學習宿效率的使用 Eclipse 。