Transcript
Page 1: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

物件導向程式設計是目前程式設計的潮流,Java語言是一種真正的物件導向程式語言,使用 Java 撰寫的程式碼會自然溶入物件導向的觀念,這是學習物件導向程式設計的最佳程式語言。

Android是一套使用 Linux作業系統為基礎開發的開放原始碼(Open Source)作業系統,最初主要是針對手機等行動裝置使用的作業系統,現在 Android 已經逐漸擴充到平板電腦、筆電和其他領域,例如:電子書閱讀器、MP4 播放器和Internet電視等。

在規劃上,本書可以作為大專院校第一門程式語言(取代傳統 Swing或 AWT的 Java 語言)、物件導向程式設計或手機程式設計課程的教材,更可以讓初學程式設計者從 Java語言開始,輕鬆進入 Android應用程式開發。

Android應用程式開發是目前當紅的軟體開發領域,對於不熟悉 Java語言和Android Studio的讀者,本書提供完整 Java程式語言與物件導向教學,直接使用筆者開發的輕量級 fChart 程式碼編輯器幫助讀者學習 Java 語言和物件導向程式設計後,才真正使用 Android Studio整合開發環境進入 Android應用程式開發,讓讀者從基礎 Java語言開始來深入學習 Android平台程式設計。

fChart程式設計教學工具本來是專為初學者開發的一套流程圖直譯器,不只可以繪製流程圖,更可以使用直譯方式執行流程圖來驗證執行結果,整合 fChart程式碼編輯器(源於 Min C# Lab),可以讓讀者繪製流程圖且驗證正確後,馬上啟動編輯器來將流程圖符號一一自行轉換成指定語言的程式碼。

因為 Android應用程式開發是 Java技術的延伸,讀者需要學習 Java語言之後,才能真正進行 Android應用程式開發,有鑑於此,筆者替換傳統 Java語言的

Page 2: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

iii

視窗程式設計章節,改為 Android應用程式開發,讓 Java語言和實務結合,以便讀者可以輕鬆進入當紅的軟體開發領域。

在 Java語言部分,筆者不只詳細說明 Java語言的基本語法和程式設計,更使用大量圖例和 UML類別圖來說明物件導向觀念,可以幫助讀者學習物件導向的思考模式,使用物件導向程式設計來解決問題。

如何閱讀本書

本書架構是循序漸進由流程圖 Java程式開發環境建立開始,依序安裝 JDK、

Windows作業系統的環境設定和 fChart程式碼編輯器後,才進入基礎 Java語法的說明,物件導向程式設計的觀念,最後在第三篇才從官方 Android Studio開發工具的安裝和設定開始,進入 Android應用程式開發。

第一篇:Java結構化程式設計

第一篇內容屬於 Java 基礎的 Java 結構化程式設計,在第 1 章說明如何在Windows作業系統安裝 JDK來建立 Java開發環境。然後在第 2章使用 fChart程式碼編輯器來建立 Java 程式(提供 fChart 流程圖的程式執行流程,和對應流程圖符號的功能表指令,可以讓我們直接執行指令來快速以程式碼片段建立 Java程式),和詳細說明 Java程式的基本架構。

第 3~6 章是 Java 語言的基礎,屬於傳統結構化程式語言的變數、運算子、流程控制和程序與函數的方法,再加上陣列和字串。Java 初學者請詳細閱讀本篇,以便建立基本 Java程式設計能力。

第二篇:Java物件導向程式設計

第二篇內容是 Java 物件導向程式設計,第 7~9 章依序說明類別與物件、繼承、多型、介面、巢狀類別、抽象類別和套件,筆者使用大量程式範例輔以 UML類別圖,可以輕鬆帶領讀者進入物件導向程式設計的天空。在第 10 章說明例外處理、執行緒和泛型集合物件,並且說明 Lambda運算式、函數介面和預設方法。

Page 3: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

iv

第三篇:Android App 行動應用程式開發

第三篇內容是 Android應用程式開發,第 11章是 XML與 Android的基礎,和官方 Android Studio 開發環境的建立,最後說明如何使用 Android 模擬器AVD,也就是 Android作業系統的基本使用。在第 12章建立第 1個 Android應用程式後,說明 Android使用介面的建立和事件處理,包含版面配置與介面元件。第 13章在詳細說明活動的生命週期後,說明如何建立元件的事件處理。

第 14 章說明如何使用意圖與意圖篩選來建立多活動的 Android 應用程式,和啟動作業系統內建的應用程式。在第 15 章是進階使用介面的動作列選單、對話方塊與清單介面(Spinner 和 ListView 元件)。第 16 章是儲存程式資料的偏好設定、檔案與 SQLite資料庫。在第 17章說明內容提供者、廣播接收器與訊息提醒的系統服務。最後第 18章說明 GPS定位服務、繪圖與多媒體。

編著本書雖力求完美,但學識與經驗不足,謬誤難免,尚祈讀者不吝指正。

陳會安 [email protected]

2018.11.11於台北

版權聲明

本書範例檔內含的共享軟體或公共軟體,其著作權皆屬原開發廠商或著作

人,請於安裝後詳細閱讀各工具的授權和使用說明。內含軟體提供本書讀者練習

之用,與各軟體的著作權和其他利益無涉,如果在使用過程中因軟體所造成的任

何損失,與本書作者和出版商無關。

Page 4: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-1 | 程序與函數的基礎

「程序」(Subroutines或 Procedures)是一個擁有特定功能的獨立程式單元,可以讓我們重複使用之前已經建立的程序,而不用每次都重複撰寫相同功能的程

式碼。一般來說,程式語言會將獨立程式單元分為程序和函數二種,程序沒有傳

回值;有傳回值稱為「函數」(Functions)。

5-1-1 程序與函數的結構

不論是日常生活,或實際撰寫程式碼時,有些工作可能會重複出現,而且這

些工作不是單一程式敘述,而是完整的工作單元,例如:我們常常在自動販賣機

購買茶飲,此工作的完整步驟,如下所示:

將硬幣投入投幣口

按下按鈕,選擇購買的茶飲

在下方取出購買的茶飲

上述步驟如果只有一次到無所謂,如果幫 3位同學購買果汁、茶飲和汽水三種飲料,這些步驟就需重複 3次,如下所示:

3

2

1

類別方法 Chapter 5

Page 5: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-2

PART 1 Java 結構化程式設計

想信沒有同學請你幫忙買飲料時,每一次都說出左邊 3個步驟,而會很自然的簡化成 3個工作,直接說:

購買果汁 購買茶飲 購買汽水

上述簡化的工作描述就是函數(Functions)的原型,因為我們會很自然的將一些工作整合成更明確且簡單的描述「購買??」。程式語言也是使用想同觀念,可以將整個自動販賣機購買飲料的步驟使用一個整合名稱來代表,即【購買()】函數,如下所示:

購買(果汁) 購買(茶飲) 購買(汽水)

上述程式碼是函數呼叫,在括號中是傳入購買函數的資料,即引數

(Arguments),以便 3 個操作步驟知道購買哪一種飲料,執行此函數的結果是拿到飲料,這就是函數的傳回值。

5-1-2 程序與函數是一個黑盒子

我們並不需要了解程序與函數實作的程式碼,也不想知道其細節,程序與函

數如同是一個「黑盒子」(Black Box),只要告訴我們如何使用黑盒子的「使用介面」(Interface)即可,如下圖所示:

Page 6: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-3

5 類別方法

上述使用介面是呼叫程序或函數的對口單位,可以傳入參數和取得傳回值。

簡單的說,使用介面是程序與函數對外的溝通管道,一個對外的邊界。程序與函

數真正的內容是隱藏在使用介面之後,「實作」(Implementation)就是在撰寫程序與函數的程式碼。

一般來說,程序與函數的「語法」(Syntactic)說明程序與函數需要傳入何種資料型態的「參數」(Parameters)和傳回值,「語意」(Semantic)是描述程序與函數可以作什麼事?在撰寫程序與函數時,我們需要了解程序與函數的語

法規則;呼叫程序與函數時需要了解程序與函數的語意規則,如此才能夠正確的

呼叫程序與函數。

5-2 | 建立類別方法

Java 語言的程序與函數是一種類別的成員,稱為「方法」(Methods),簡單的說,在 Java語言撰寫的程序或函數稱為方法。

5-2-1 建立 Java的類別方法

方法(Methods)分為屬於類別的「類別方法」(Class Methods)和物件的「實例方法」(Instance Methods)兩種。在本章說明的是類別方法,相當於其他程式語言的程序和函數,實例方法的說明請參閱<第 7章:類別與物件>。

建立類別方法

Java語言的類別方法是由方法名稱和程式區塊所組成,其語法如下所示:

Page 7: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-4

PART 1 Java 結構化程式設計

存取特性子 static 傳回值型態 方法名稱( 參數列 ) { …… 程式敘述; …… }

上述方法是「靜態方法」(Static Method),因為使用 static「修飾子」(Modifiers)。在最前面是「存取特性子」(Access Specifier),這也是一種修飾子,常用的有:public和 private,其說明如下所示:

public:方法可以在程式任何地方進行呼叫,甚至是其他類別。

private:方法只能在同一個類別內進行呼叫。

例如:一個沒有傳回值和參數列的 printTriangle()方法,可以顯示一個字元三角形,如下所示:

private static void printTriangle() { int i, j; for ( i = 5; i >= 1; i-- ) { for ( j = 1; j <= i; j++ ) System.out.print("*"); System.out.print("\n"); } }

上述方法的傳回值型態為 void,表示沒有傳回值,方法名稱為 printTriangle,括號內是傳入的參數列,因為方法沒有參數所以是空括號,在「{」和「}」括號之中就是方法的程式區塊,使用兩層巢狀迴圈顯示星號字元的三角形。

呼叫類別方法

在 Java程式碼呼叫類別方法是使用類別和方法名稱,其語法如下所示:

方法名稱( 參數列 ); 類別名稱.方法名稱( 參數列 );

因為 printTriangle() 方法沒有傳回值和參數列,所以呼叫方法只需使用方法名稱加上空括號即可,如下所示:

printTriangle();

Page 8: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-5

5 類別方法

上述方法呼叫因為是在同一個類別,所以可以省略類別名稱。如果在其他類

別呼叫此類別方法,例如:public修飾子的 sumOne2Five() 方法,其呼叫的程式碼,如下所示:

Ch5_2_1.sumOne2Five();

上述 Ch5_2_1是類別名稱,使用「.」運算子呼叫類別方法 sumOne2Five()。

Java 程式:Ch5_2_1.java

在 Java程式建立 2個類別方法,其中 1加到 5是由第 4章迴圈程式區塊所 改寫,其執行結果可以顯示星號三角形和 1加到 5的總和 15,如下所示:

***** **** *** ** * |1|2|3|4|5 總和: 15

程式內容 01: public class Ch5_2_1 { 02: // 類別方法: 顯示星號三角形

03: private static void printTriangle() { 04: int i, j; // 變數宣告

05: // for巢狀迴圈

06: for ( i = 5; i >= 1; i-- ) {

07: for ( j = 1; j <= i; j++ )

08: System.out.print("*");

09: System.out.print("\n");

10: }

11: } 12: // 類別方法: 計算 1加到 5的總和

13: public static void sumOne2Five() { 14: int i, sum = 0;; // 變數宣告

15: // for迴圈敘述

16: for ( i = 1; i <= 5; i++ ) {

17: System.out.print("|" + i);

18: sum += i;

19: }

Page 9: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-6

PART 1 Java 結構化程式設計

20: System.out.println("\n總和: " + sum);

21: } 22: // 主程式

23: public static void main(String[] args) { 24: // 類別方法的呼叫

25: printTriangle(); 26: // 另一種類別方法的呼叫

27: Ch5_2_1.sumOne2Five();

28: }

29: }

程式說明

第 3~11列:private類別方法,使用巢狀迴圈顯示星號的三角形。

第 13~21列:public類別方法,程式區塊就是第 4章迴圈的 1加到 5,此方法是用來說明如何將程式區塊改頭換面成為方法。

第 25列:呼叫 printTriangle() 方法。

第 27列:指明類別名稱,以類別名稱呼叫 sumOne2Five() 方法。

類別方法的執行過程

Java 程式如何執行類別方法,以本節範例為例,程式是在 main() 主程式的第 25 列呼叫 printTriangle() 方法,此時程式碼執行順序就跳到 printTriangle() 方法的第 3列,在執行完第 11列後返回呼叫點,如下圖所示:

Page 10: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-7

5 類別方法

然後繼續執行程式,在第 27列呼叫 sumOne2Five() 方法,程式碼跳到此方法的第 13列,在執行完第 21列返回呼叫點即完成程式執行。很明顯的!方法只是更改程式碼的執行順序,在呼叫點跳到方法來執行(保留狀態),在執行完後,

回到程式的呼叫點(回存狀態後)繼續執行其他程式碼。

5-2-2 類別方法的參數傳遞

Java方法的參數列是資訊傳遞的機制,可以讓我們從外面將資訊送入方法的黑盒子,換句話說,參數列就是方法的使用介面。

如果方法擁有參數列,在呼叫方法時,即可傳入不同參數來產生不同的執行

結果。例如:擁有 2個參數的 sumN2N() 方法,如下所示:

static void sumN2N(int start, int end) { int i, sum = 0; for ( i = start; i <= end; i++ ) { System.out.print("|" + i); sum += i; } System.out.print("\n"+ start + "到" + end); System.out.println("的總和: " + sum); }

上述 sumN2N() 方法可以計算參數範圍的總和,其定義的參數稱為「正式參數」(Formal Parameters)或「假的參數」(Dummy Parameters)。正式參數是識別字,其角色如同變數,需要指定資料型態,並且可以在方法的程式區塊中

使用,如果參數不只一個請使用「,」符號分隔。

Java方法如果擁有參數列,在呼叫時就需要加上傳入的參數,如下所示:

sumN2N(1, max);

上述方法呼叫的參數稱為「實際參數」(Actual Parameters),此為參數值,例如:1,也可以是運算式,例如:max變數,其運算結果的值需要和正式參數定義的資料型態相同,而且在方法的每一個正式參數對應一個同型態的實際參數。

Page 11: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-8

PART 1 Java 結構化程式設計

Java 程式:Ch5_2_2.java

在 Java程式建立 2個類別方法擁有參數列,第 1個方法可以轉換溫度,第 2個方法計算從 n加到 n的總和,其執行結果如下所示:

請輸入攝氏溫度=> 100.0 Enter 請輸入最大值=> 15 Enter 攝氏 華氏 100.0 212.0 |1|2|3|4|5|6|7|8|9|10|11|12|13|14|15 1到 15的總和: 120 |6|7|8|9|10 6到 10的總和: 40

上述執行結果輸入溫度和最大值後,可以顯示轉換成華氏的溫度,然後是 1加到 15和 6加到 10的總和 120和 40。

程式內容 01: public class Ch5_2_2 { 02: // 類別方法: 轉換溫度

03: static void convertTemp(double c) { 04: double f; // 變數宣告

05: System.out.println("攝氏\t華氏");

06: f = (9.0 * c) / 5.0 + 32.0;

07: System.out.println(c + "\t" + f);

08: } 09: // 類別方法: 計算 N到 N的數字總和

10: static void sumN2N(int start, int end) { 11: int i, sum = 0; // 變數宣告

12: // for迴圈敘述

13: for ( i = start; i <= end; i++ ) {

14: System.out.print("|" + i);

15: sum += i;

16: } 17: System.out.print("\n"+ start + "到" + end);

18: System.out.println("的總和: " + sum);

19: } 20: // 主程式

21: public static void main(String[] args) { 22: java.util.Scanner sc = // 建立 Scanner物件

23: new java.util.Scanner(System.in); 24: System.out.print("請輸入攝氏溫度=> ");

Page 12: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-9

5 類別方法

25: double c = sc.nextDouble(); // 取得溫度

26: System.out.print("請輸入最大值=> ");

27: int max = sc.nextInt(); // 取得最大值

28: convertTemp(c); // 類別方法的呼叫

29: sumN2N(1, max);

30: Ch5_2_2.sumN2N(6, 10);

31: }

32: }

程式說明

第 3~8列:convertTemp() 類別方法擁有 1個參數,因為沒有使用 public或 private,表示是預設存取方式,可以在同一個「套件」(Package)存取,而不能在其他套件存取,詳細的套件說明請參閱<第 9 章:巢狀類別、多型與套件>。

第 10~19列:sumN2N() 類別方法擁有 2個參數,程式區塊的迴圈可以從第 1個參數加到第 2個參數。

第 22~27 列:建立 Scanner 物件取得使用者輸入的溫度變數 c 和最大值變數 max。

第 28列:呼叫 convertTemp() 方法需要 1個參數,可以顯示轉換成的華氏溫度。

第 29~30列:使用不同參數呼叫 2次 sumN2N() 方法,可以得到不同的執行結果。

5-2-3 類別方法的傳回值

Java方法的傳回值型態如果不是 void,而是其他資料型態 int或 char等時,就表示方法擁有傳回值,這種擁有傳回值的類別方法稱為函數(Functions)。

在 Java 方法的程式區塊是使用 return 關鍵字來回傳一個值。傳回值的型態 需要與方法宣告的傳回值型態相同,例如:轉換溫度的 convertTemp() 方法是一個擁有傳回值的方法,如下所示:

Page 13: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-10

PART 1 Java 結構化程式設計

static double convertTemp(double c) { return (9.0 * c) / 5.0 + 32.0; }

上述 convertTemp() 方法的傳回值型態為 double,可以計算傳入參數 c的華氏溫度,使用 return關鍵字傳回方法的執行結果。

當 Java方法擁有傳回值時,呼叫方法就需要使用指定敘述來取得回傳值,如下所示:

f = convertTemp(100.0);

上述變數 f可以取得方法的回傳值,而且變數 f的資料型態需要與方法傳回值的資料型態相符。

Java 程式:Ch5_2_3.java

在 Java程式建立計算區間整數總和與溫度轉換的 2個函數方法,其執行結果如下所示:

請輸入攝氏溫度=> 100.0 Enter 請輸入開始值=> 5 Enter 請輸入結束值=> 15 Enter 5加到 15的總和:110 100.0度 C=212.0度 F

上述執行結果輸入溫度和範圍值後,可以計算 5到 15的總和為 110,下方是攝氏 100.0度轉換成華氏溫度的值。

程式內容 01: public class Ch5_2_3 {

02: static double convertTemp(double c) {

03: return (9.0 * c) / 5.0 + 32.0;

04: } 05: // 類別方法: 計算 N到 N的數字總和

06: static int sumN2N(int start, int end) { 07: int i, sum = 0; // 變數宣告

08: // for迴圈敘述

Page 14: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-11

5 類別方法

09: for ( i = start; i <= end; i++ )

10: sum += i;

11: return sum;

12: } 13: // 主程式

14: public static void main(String[] args) { 15: java.util.Scanner sc = // 建立 Scanner物件

16: new java.util.Scanner(System.in); 17: System.out.print("請輸入攝氏溫度=> ");

18: double c = sc.nextDouble(); // 取得溫度

19: System.out.print("請輸入開始值=> ");

20: int s = sc.nextInt(); // 取得開始值

21: System.out.print("請輸入結束值=> ");

22: int e = sc.nextInt(); // 取得結束值

23: // 類別方法的呼叫

24: int total = sumN2N(s, e); 25: System.out.println(s+"加到"+e+"的總和:"+total);

26: double f = convertTemp(c); 27: System.out.println(c + "度 C=" + f + "度 F");

28: }

29: }

程式說明

第 2~4列:convertTemp() 類別方法傳回值的資料型態為 double,在第 3列使用 return關鍵字傳回溫度轉換的結果。

第 6~12列:sumN2N() 類別方法傳回值的資料型態為 int,在第 11列的

return關鍵字傳回方法的執行結果。

第 15~22 列:建立 Scanner 物件取得使用者輸入的溫度變數 c 和範圍變數 s與 e。

第 24列:呼叫 sumN2N() 方法,並且將回傳值指定給變數 total。

第 26列:呼叫 convertTemp() 方法。

5-2-4 傳值或傳址參數

Java方法傳入的參數有兩種參數傳遞方式,其說明如下表所示:

Page 15: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-12

PART 1 Java 結構化程式設計

傳遞方式 說明

傳值呼叫(Call by Value) 將變數的值傳入方法,方法另外配置記憶體儲存參數值,所

以不會變更呼叫變數的值

傳址呼叫(Call by Reference) 將變數實際儲存的記憶體位址傳入,如果在方法變更參數

值,也會同時變動原呼叫的變數值

Java傳址呼叫參數主要是指「物件實例」(Object Instance)。事實上,方法參數依不同資料型態有不同的傳遞方式,如下表所示:

資料型態 方式 說明

int、char 和 double 等基本資料型態

傳值 基本資料型態的參數傳遞是使用傳值方式

String物件 傳值 不論是否使用 new運算字建立字串物件都是傳值,因為字串物件並不能更改字串內容

Array陣列 傳址 Java陣列是一種物件,其參數傳遞方式是傳址方式

上表陣列和 String物件的詳細說明請參閱<第 6章:陣列與字串>,在本節

只是用來說明方法的參數傳遞方式。

Java 程式:Ch5_2_4.java

在 Java程式建立 2個類別方法 funcA() 和 funcB(),可以測試各種資料型態參數的傳遞方式,其執行結果如下所示:

呼叫 funcA前: 1-true 在 funcA為 :2-false 呼叫 funcA後: 1-true 呼叫 funcB前: 2-張無忌 在 funcB為 : 150-江小魚 呼叫 funcB後: 150-張無忌

上述執行結果可以看到 funcA() 方法的整數和布林型態參數,在其呼叫前後並沒有改變。在 funcB() 方法的參數是陣列和 String字串物件,其呼叫前後的陣列元素已經改變,String物件沒有改變。

Page 16: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-13

5 類別方法

程式內容 01: public class Ch5_2_4 { 02: // 類別方法: integer和 boolean型態參數為傳值

03: static void funcA(int c, boolean b) { 04: c++; 05: b = false; 06: System.out.println("在 funcA為 :"+c+"-"+b);

07: } 08: // 類別方法: 陣列與字串物件參數為傳址

09: static void funcB(int temp[], String a) { 10: temp[1] = 150; 11: a = "江小魚"; 12: System.out.println("在 funcB為 : "+temp[1]+"-"+a);

13: } 14: // 主程式

15: public static void main(String[] args) { 16: // 變數宣告 17: int c = 1; // 數字 18: boolean b = true; // 布林 19: String str = "張無忌"; // 字串 20: int arr[] = { 1, 2, 3 }; // 陣列 21: System.out.println("呼叫 funcA前: "+c+"-"+b); 22: // 呼叫類別方法

23: funcA(c, b); 24: System.out.println("呼叫 funcA後: "+c+"-"+b); 25: System.out.println("呼叫 funcB前: "+arr[1]+"-"+str); 26: // 呼叫類別方法

27: funcB(arr, str); 28: System.out.println("呼叫 funcB後: "+arr[1]+"-"+str);

29: } 30: }

程式說明

第 3~7列: funcA() 類別方法測試整數和布林基本資料型態的參數傳遞,在第 4~5列更改參數值。

第 9~13列:funcB() 類別方法測試陣列和 String物件的參數傳遞,在第10列更改陣列索引 1的值,第 11列更改 String物件的值。

第 17~20列:宣告各種資料型態的變數,並且指定初值。

第 23和 27列:分別呼叫 funcA() 和 funcB() 方法。

Page 17: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-14

PART 1 Java 結構化程式設計

5-3 | 類別變數和變數範圍

Java類別除了包含類別方法外,還可以擁有宣告成 static的變數,此種變數是屬於類別的變數,我們可以將它視為其他程式語言所謂的「全域變數」(Global Variables)。

如果是在方法內程式區塊宣告的變數,稱為「區域變數」(Local Variables)。

5-3-1 Java的類別變數

在 Java類別宣告的成員變數是一種類別成員,當使用 static修飾子時,成員變數就屬於類別本身,稱為「類別變數」(Class Variables)。

Java的類別變數是當類別第一次建立時,就配置變數的記憶體,直到類別不存在為止。類別變數在類別中的所有方法都可以存取其值,其宣告的位置是位在

其他方法的外面,如下所示:

public class Ch5_3_1 { static int no = 1; …………… }

上述程式碼宣告類別變數 no,存取特性子 public和 private一樣可以使用在類別變數。如果沒有使用 private,表示類別變數可以被其他類別存取,請注意!如果在其他類別存取時,需要指名類別名稱,如下所示:

Ch5_3_1.no

Java成員變數在宣告後,就算沒有指定初值,也會擁有預設初值,數值型態為 0,boolean型態為 false,char型態為 Unicode的 0,如果是物件,其預設值為 null。

Page 18: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-15

5 類別方法

Java 程式:Ch5_3_1.java

在 Java程式宣告類別變數 no後,分別在主程式 main() 和類別方法 funcA() 更改變數值,其執行結果如下所示:

類別變數初值 : 1 呼叫 funcA 前 : 2 呼叫 funcA 後 : 3

上述執行結果可以看到類別變數的初值為 1,在 main() 主程式改為 2後,在funcA() 方法改為 3。

程式內容 01: public class Ch5_3_1 { 02: // 類別變數宣告

03: static int no = 1; 04: // 類別方法

05: static void funcA() { 06: no = 3; // 指定類別變數值

07: } 08: // 主程式

09: public static void main(String[] args) { 10: System.out.println("類別變數初值 : " + no);

11: no = 2; // 指定類別變數值

12: System.out.println("呼叫 funcA 前 : " + no);

13: funcA(); // 呼叫類別方法

14: System.out.println("呼叫 funcA 後 : " + no);

15: }

16: }

程式說明

第 3列:宣告類別變數 no且指定初值為 1。

第 5~7列:類別方法 funcA() 在第 6列指定類別變數值為 3。

第 11列:在主程式 main() 指定類別變數值為 2。

第 13列:呼叫 funcA() 方法。

Page 19: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-16

PART 1 Java 結構化程式設計

5-3-2 Java的變數範圍

Java變數分為類別的成員變數、「方法參數」(Method Parameters)和區域變數。「變數範圍」(Scope)可以影響變數值的存取,即決定有哪些程式碼可以存取此變數。Java變數範圍的說明,如下所示:

區域變數範圍(Local Variable Scope):在方法內宣告的變數,只能在宣告程式碼後的程式碼使用(不包括宣告前),在方法外的程式碼並無

法存取此變數。

方法參數範圍(Method Parameter Scope):傳入方法的參數變數範圍是整個方法的程式區塊,在方法外的程式碼並無法存取。

成員變數範圍(Member Variable Scope):不論是 static的類別變數或沒有宣告 static(此為物件的實例變數,詳見第 7章),整個類別的程式碼都可以存取此變數。

筆者已經將上述變數範圍整理成圖形,如下圖所示:

Java 程式:Ch5_3_2.java

在 Java程式建立 3個類別方法 funcA()、funcB() 和 funcC(),可以測試各種

Java變數的範圍,其執行結果如下所示:

呼叫 funcA前: 1 - 2.0 funcA變數宣告前: 1 - 2.0 funcA變數宣告後: 3 - 4.0 呼叫 funcA後: 1 - 2.0

Page 20: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-17

5 類別方法

呼叫 funcB前: 1 - 2.0 funcB參數設定前: 5 - 6.0 funcB參數設定後: 3 - 4.0 呼叫 funcB後: 1 - 2.0 呼叫 funcC前: 1 - 2.0 呼叫 funcC後: 3 - 4.0

上述執行結果可以看到 funcA() 的 2 個變數,宣告前的類別變數值為 1 和

2.0,在宣告後成為 3和 4.0,因為顯示的是區域變數值。

在 funcB() 傳入的參數值為 5 和 6.0,3 和 4.0 是設定後的參數值。最後 funcC() 指定類別變數的值,所以在呼叫後類別變數成為 3和 4.0。

程式內容 01: public class Ch5_3_2 { 02: // 類別變數宣告

03: static int a = 1; 04: static double b = 2.0; 05: // 類別方法: 區域變數的範圍

06: static void funcA() { 07: System.out.println("funcA變數宣告前: "+a+" - "+b); 08: // 區域變數宣告

09: int a = 3; 10: double b = 4.0; 11: System.out.println("funcA變數宣告後: "+a+" - "+b);

12: } 13: // 類別方法: 方法參數的範圍

14: static void funcB(int a, double b) { 15: System.out.println("funcB參數設定前: "+a+" - "+b); 16: a = 3; // 設定參數變數 17: b = 4.0; // 設定參數變數 18: System.out.println("funcB參數設定後: "+a+" - "+b);

19: } 20: // 類別方法: 類別變數的範圍

21: static void funcC() { 22: a = 3; // 設定類別變數 23: b = 4.0; // 設定類別變數

24: } 25: // 主程式

26: public static void main(String[] args) { 27: System.out.println("呼叫 funcA前: "+a+" - "+b); 28: funcA(); // 呼叫類別方法 29: System.out.println("呼叫 funcA後: "+a+" - "+b);

Page 21: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-18

PART 1 Java 結構化程式設計

30: System.out.println("呼叫 funcB前: "+a+" - "+b); 31: funcB(5, 6.0); // 呼叫類別方法 32: System.out.println("呼叫 funcB後: "+a+" - "+b); 33: System.out.println("呼叫 funcC前: "+a+" - "+b); 34: funcC(); // 呼叫類別方法 35: System.out.println("呼叫 funcC後: "+a+" - "+b);

36: } 37: }

程式說明

第 3~4列:宣告 int和 double的類別變數且指定初值。

第 6~12列:funcA() 類別方法測試區域變數的範圍,在第 9~10列宣告區域變數。

第 14~19列:funcB() 類別方法測試方法參數的範圍,在第 16~17列更改參數值。

第 21~24 列:funcC() 類別方法測試成員/類別變數的範圍,在第 22~23列更改類別變數值。

第 28、31和 34列:分別呼叫 funcA()、funcB() 和 funcC() 方法。

5-4 | 遞迴程式設計

「遞迴」(Recursive)是程式設計的一個重要觀念。「遞迴函數」(Recursive Functions)在 Java稱為「遞迴方法」(Recursive Methods),可以讓程式碼變的很簡潔,但是設計遞迴方法需要很小心,不然很容易掉入無窮方法呼叫的陷阱。

5-4-1 遞迴方法的基礎

遞迴是由上而下分析方法的一種特殊的情況,使用遞迴觀念建立的方法稱為

遞迴方法,其基本定義如下所示:

一個問題的內涵是由本身所定義的話,稱之為遞迴。

Page 22: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-19

5 類別方法

因為遞迴問題在分析時,其子問題本身和原來問題擁有相同的特性,只是範

圍改變,範圍逐漸縮小到終止條件,所以可以歸納出遞迴方法的兩個特性,如下

所示:

遞迴方法在每次呼叫時,都可以使問題範圍逐漸縮小。

遞迴方法需要擁有終止條件,以便結束遞迴方法的執行。

5-4-2 遞迴的階層函數

遞迴方法最常見的應用是數學上定義的階層函數 n!,如下所示:

例如:我們準備計算 4! 的值,從上述定義 n>0,可以使用 n! 定義的第二條計算階層函數 4! 的值,如下所示:

4!=4*3*2*1=24

因為階層函數本身擁有遞迴特性。可以將 4! 的計算分解成子問題,如下所示:

4!=4*(4-1)!=4*3!

現在 3! 的計算成為一個新的子問題,必須先計算出 3! 值後,才能處理上述的乘法。同理將子問題 3! 繼續分解,如下所示:

3! = 3*(3-1)! = 3*2! 2! = 2*(2-1)! = 2*1! 1! = 1*(1-1)! = 1*0! = 1*1 = 1

最後我們知道 1! 的值,接著可以計算 2!~4!,如下所示:

2! = 2*(2-1)! = 2*1! = 2 3! = 3*(3-1)! = 3*2! = 3*2 = 6 4! = 4*(4-1)! = 4*3! = 24

Page 23: Google Android 應用程式開發實戰epaper.gotop.com.tw/PDFSample/AEL021800.pdf · 物件導向程式設計是目前程式設計的潮流, Java 語言是一種真正的物件導向

5-20

PART 1 Java 結構化程式設計

上述階層函數的子問題是一個階層函數,只是範圍改變逐漸縮小到一個終止

條件。以階層函數為例子是 n=0。等到到達終止條件,階層函數值也就計算出來。

Java 程式:Ch5_4_2.java

在 Java程式建立遞迴的階層函數,可以計算階層函數的值,其執行結果如下所示:

請輸入最大階層=> 6 Enter 6!函數的值:720

上述執行結果輸入最大階層為 6,可以看到 6! 的值為 720。

程式內容 01: public class Ch5_4_2 { 02: // 遞迴方法: 計算階層函數的值

03: static int factorial(int n) { 04: if ( n == 1 ) // 終止條件

05: return 1;

06: else

07: return n * factorial(n-1);

08: } 09: // 主程式

10: public static void main(String[] args) { 11: java.util.Scanner sc = // 建立 Scanner物件

12: new java.util.Scanner(System.in); 13: System.out.print("請輸入最大階層=> ");

14: int no = sc.nextInt(); // 取得最大階層

15: System.out.println(no+"!函數的值:"+factorial(no));

16: }

17: }

程式說明

第 3~8列:階層函數的 factorial() 遞迴方法,在第 4~7列的 if條件是遞迴的終止條件,在第 7列遞迴呼叫自已,只是參數的範圍縮小 1。

第 11~14列:建立 Scanner物件取得使用者輸入最大階層數的變數 no。

第 15列:呼叫 factorial() 遞迴方法。


Recommended