23
物件導向程式設計是目前程式設計的潮流,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 語言的

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

  • Upload
    others

  • View
    11

  • Download
    0

Embed Size (px)

Citation preview

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() 遞迴方法。