--- tags: Java --- # Java--類別與物件 >參考資料: >* http://www.codedata.com.tw/book/java-basic-source/ch11-1.htm >* https://caterpillar.gitbooks.io/javase6tutorial/content/c7_1.html >* https://noob.tw/java-oop/ >* http://pclevin.blogspot.com/2013/02/java-java-return.html ## 定義類別 (class) ### 以物件思考問題 * 物件導向的思維:以物件為中心來思考問題 1. 識別出問題中的物件 2. 識別出物件上的屬性 * 屬性(Property):物件上的靜態特性。即物件上擁有的特徵或是可表示的狀態(State)。名詞,例如:顏色或尺寸 3. 識別出物件上可操作的方法 * 方法:物件上的動態特性。即物件本身可操作或供操作的介面。動詞,例如:寫程式、跑步 4. 產生物件實例 從物件定義書中產生物件實例,並以這些物件實例設計彼此間的交互行為以解決問題 範例:有一個帳戶,帳戶中有存款餘額,您可以對帳戶進行存款與提款的動作,並可以查詢以取得存款餘額。 * 識別出問題中的物件與屬性: ![](https://i.imgur.com/7laZCer.png) * 識別出物件上可操作的方法: ![](https://i.imgur.com/7UihQE1.png) * 從物件定義書中產生物件實例 ![](https://i.imgur.com/zuADjjG.png) * 類別建立的物件就是類別的實例(Instance) >實例就是一個物件 ## 使用 class 定義類別 * 類別(Class):規格書 >使用類別定義出物件的規格書,之後根據類別來建構出一個個的物件,然後透過物件所提供的操作介面來與程式互動。 舉例:為「帳戶」這個物件定義了 Account 類別 範例:Account.java ```java= public class Account { private String accountNumber; private double balance; public Account() { this("empty", 0.0); } public Account(String accountNumber, double balance) { this.accountNumber = accountNumber; this.balance = balance; } public String getAccountNumber() { return accountNumber; } public double getBalance() { return balance; } public void deposit(double money) { balance += money; } public double withdraw(double money) { balance -= money; return money; } } ``` ![](https://i.imgur.com/sO6vyc9.png) ### 類別宣告 (Class declaration) :::info ```java= [modifier] class class_identifier { // ..類別本體 } ``` * modifier 被使用來決定此類別相對於其它類別的存取權。modifier 可有可無,可以是 public、abstract、或是 final * class 關鍵字告訴編譯器此程式區塊為一類別宣告 * class_identifier 是你給予類別的名稱 ::: * 在一個檔案中可以定義數個類別,但只能有一個類別被設定為 "public",檔案名稱主檔名必須與這個 public 的類別同名 例如: ```java= public class Account { // 檔案必須是Account.java // 實作內容 } class SomeClass { //實作內容 } class OtherClass { //實作內容 } ``` * 宣告類別後,Java可以將類別當作資料型態,利用資料型態來宣告物件變數 範例: ![](https://i.imgur.com/sMRp3Kc.png) ![](https://i.imgur.com/AnMPur3.png) ![](https://i.imgur.com/hD4rjK9.png) * 基本原則:資訊的最小化公開 >儘量透過方法來操作物件,而不直接存取物件內部的資料成員 ### 類別本體 (Class body) * 類別本體中主要包括三個部份:變數( Variable )、建構式( Constructor )、方法( Method ) #### 變數 (Variable)/值域 (Field)/資料成員 (Data member) * 變數即為表示物件的屬性(特徵) * 宣告變數時依資料型態不同而有不同的預設值 ![](https://i.imgur.com/2DaNvzu.png) >類別變數在宣告時使用 private 關鍵字修飾,表示這個類別變數只能被在類別本體中定義的方法(Method)存取,外部物件無法直接存取,這樣的資料成員稱之為私用成員(Private member)。外部物件只能透過公開的(Public)操作介面才可以間接存取到私用成員(如果類別中有定義這樣的操作介面)。 >類別變數宣告時的權限修飾是可有可無的。預設是在同一個套件管理下的類別都可以存取該類別變數 #### 建構式/建構方法/建構子 ( Constructor ) * 與類別名稱同名 * 可以被重載(Overload) * 作用:建構物件的同時,可以同時初始一些必要的資訊。例如:指定引數 * 不具有返回值(Return value),也不用加上 void * 建構物件時要使用 "new" 關鍵字 > 執行哪一個建構式,依照實例化時給定哪一種型態的引數而決定 * 預設建構式 (Default constructor):公開且無參數 範例: ![](https://i.imgur.com/xVrr6pH.png) ![](https://i.imgur.com/cZ7BT9b.png) #### 方法 (Method) * 方法是物件擁有的操作能力(Operation),也可表現出物件的行為(Behavior) * 可以返回一個值,表示方法執行完畢後的運算結果 * 加上 **void**,表示這個方法執行完畢後不必返回任何值 ## 類別方法 (Method) ### 定義方法 :::info ```java= [modifier] type1 identifier(type2 param, ...) { [return data;] } ``` * modifier:權限修飾。 >可以使用 public、protected、private 來修飾,分別將方法修飾為公開的、保護的或私用的 * type1:返回值型態。 >可以使用基本資料型態,也可以是自定義的物件型態,如果方法執行完畢後不返回任何資料,則設定為 void * identifier:方法名稱 * (type2 param, ...):參數列。 >設定方法可接受的引數個數與型態 * 從方法中返回值時使用 return 關鍵字並加上要返回的數值或變數。返回的數值或變數之型態必須與type1 所設定的型態相同 ::: ### static 靜態 用來宣告一個函數或者變數 * **特性一:永遠會是唯一值** >永遠只佔著那一組記憶體空間。不管該類別被new幾個object,該值永遠都會是一樣的! * **特性二:可以透過類別直接存取使用** 直接使用**類別.屬性名稱**或是**類別.方法名稱** >不需要一直new物件出來 * 實例方法(非static的方法)可以直接使用static變數 * static方法不行直接呼叫使用非static變數及非static方法。若要使用,在static方法內new一個物件出來 範例: ```java= class Ball { double radius; final double PI = 3.14159; ... } ``` 若建立多個Ball物件,那每個Ball物件都會有自己的radius與PI成員 ![](https://i.imgur.com/htHOfLf.png) ```java= class Ball { double radius; static final double PI = 3.141596; ... } ``` 被宣告為static的成員,不會讓個別物件擁有,而是屬於類別,如上定義後,如果建立多個Ball物件,每個Ball物件只會各自擁有radius ![](https://i.imgur.com/mTgbNyN.png) * static方法或區塊中不能出現this關鍵字 >參考資料 >* [static 類別成員](https://openhome.cc/Gossip/Java/Static.html) >* [關鍵字 this、static 的使用](http://www.codedata.com.tw/book/java-basic-source/ch11-3.htm) >* [Java static,final 基本概念](http://blog.kenyang.net/2011/03/09/java-staticfinal) >* [JAVA的static用法](http://b0212066.pixnet.net/blog/post/204120411-java%E7%9A%84static%E7%94%A8%E6%B3%95) >* [使用 this](https://openhome.cc/Gossip/Java/This.html) ### 呼叫類別方法 :::info ```java= [類別名稱].方法名稱(參數列); ``` ::: 範例1: ![](https://i.imgur.com/ZOV2sPQ.png) ![](https://i.imgur.com/EZF8lqu.png) 範例2:(呼叫其他類別的類別方法) ![](https://i.imgur.com/bMlvErB.png) ![](https://i.imgur.com/TLKASxx.png) 範例: ```java= public class Hello{ private String name; public Hello(){ name = "nobody"; } public Hello(String one){ name = one; } public void hello(){ System.out.print("Hello "); System.out.println(name); } public void setName(String one){ name = one; } } ``` ### 類別方法的參數傳遞 * 正式參數/假參數:識別字,其角色如同變數,需要指定資料型態 * 實際參數:方法呼叫的參數,其運算結果的值需要和正式參數定義的資料型態相同 範例1: ![](https://i.imgur.com/g5KFMK8.png) ![](https://i.imgur.com/trCHLi9.png) 如果宣告的是基本型態參數,則呼叫方法時所給定的引數,會複製一份給參數; 如果宣告的是物件型態,則呼叫方法時所給定的物件,會被參數參考 範例2: ```java= public class MethodDemo{ public void primitiveParam(int para){ para = 10; } public void referParam(int[] array){ array[0] = 10; } public static void main(String[] args){ int x = 5; int[] array = {1, 2, 3, 4, 5}; MethodDemo demo = new MethodDemo(); demo.primitiveParam(x); demo.referParam(array); System.out.println("x: " + x); System.out.print("array: "); for (int element : array){ System.out.print(element); System.out.print(" "); } System.out.println(); } } ``` ![](https://i.imgur.com/IiDCfsd.png) ### 類別方法的傳回值 * 使用「return」關鍵字 * 傳回值的型態需要與方法宣告的傳回值型態相同 範例1:(無傳回值) ![](https://i.imgur.com/wAZvvsl.png) 範例2:(有傳回值) ![](https://i.imgur.com/bOLOkAR.png) ![](https://i.imgur.com/wyb4Wla.png) 範例3:(有傳回值) ![](https://i.imgur.com/QHpDAUw.png) ![](https://i.imgur.com/Q2xuq8D.png) 範例4:無返回值、無參數的hello()方法 ```java= public void hello() { System.out.print("Hello "); System.out.println(name); } Hello hello = new Hello("Java"); hello.hello(); ``` 結果:螢幕上顯示"Hello Java"的文字 ### 傳值或傳址參數 * 傳值:把變數值傳入方法,方法會另外配置記憶體儲存參數值,**不會變更原本呼叫的變數值** * **數值(int、double)、字元/字串(char、String)** * 傳址:把變數實際儲存的記憶體位置傳入,若在方法更改參數值,也會**變更原本呼叫的變數值** * **陣列(Array)** 範例: ![](https://i.imgur.com/SXjcoDX.png) ![](https://i.imgur.com/u4TAvWi.png) ### 類別變數和變數範圍 * Java語言的變數分為類別的成員變數、方法參數和區域變數 * static + 成員變數 >> 類別變數 >>不需要伴隨物件,自己就有意義了 1. 區域變數範圍:在方法內宣告的變數,只能在程式碼後使用(不包括宣告前),在方法外的程式碼並無法存取此變數。 2. 方法參數範圍:傳入方法的參數變數範圍是整個方法的程式區塊,在方法外的程式碼並無法存取。 3. 成員變數範圍:不論是static的類別變數或是沒有宣告static,整個類別的程式碼都可以存取此變數。 ![](https://i.imgur.com/xJTmgK9.png) 範例: ![](https://i.imgur.com/rKvY488.png) ![](https://i.imgur.com/jhqEvLX.png) 範例: ![](https://i.imgur.com/dq4Uheq.png) ![](https://i.imgur.com/fME8k5a.png) ### 遞迴的階層函數(Recursive) * 遞迴:一個問題的內涵是由本身所定義 1. 遞迴方法在每次呼叫時,都可以使問題範圍逐漸縮小 2. 遞迴方法需要擁有終止條件,以便結束的執行 範例: ![](https://i.imgur.com/iL5KUCE.png) ![](https://i.imgur.com/sIspdJj.png) ### Math數學類別的類別方法 * 在呼叫方法時需要指明類別Math ![](https://i.imgur.com/Eg0KaDy.png) 範例: ![](https://i.imgur.com/aRMQ7Qp.png) ![](https://i.imgur.com/uDBrBRO.png)