---
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. 產生物件實例
從物件定義書中產生物件實例,並以這些物件實例設計彼此間的交互行為以解決問題
範例:有一個帳戶,帳戶中有存款餘額,您可以對帳戶進行存款與提款的動作,並可以查詢以取得存款餘額。
* 識別出問題中的物件與屬性:

* 識別出物件上可操作的方法:

* 從物件定義書中產生物件實例

* 類別建立的物件就是類別的實例(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;
}
}
```

### 類別宣告 (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可以將類別當作資料型態,利用資料型態來宣告物件變數
範例:



* 基本原則:資訊的最小化公開
>儘量透過方法來操作物件,而不直接存取物件內部的資料成員
### 類別本體 (Class body)
* 類別本體中主要包括三個部份:變數( Variable )、建構式( Constructor )、方法( Method )
#### 變數 (Variable)/值域 (Field)/資料成員 (Data member)
* 變數即為表示物件的屬性(特徵)
* 宣告變數時依資料型態不同而有不同的預設值

>類別變數在宣告時使用 private 關鍵字修飾,表示這個類別變數只能被在類別本體中定義的方法(Method)存取,外部物件無法直接存取,這樣的資料成員稱之為私用成員(Private member)。外部物件只能透過公開的(Public)操作介面才可以間接存取到私用成員(如果類別中有定義這樣的操作介面)。
>類別變數宣告時的權限修飾是可有可無的。預設是在同一個套件管理下的類別都可以存取該類別變數
#### 建構式/建構方法/建構子 ( Constructor )
* 與類別名稱同名
* 可以被重載(Overload)
* 作用:建構物件的同時,可以同時初始一些必要的資訊。例如:指定引數
* 不具有返回值(Return value),也不用加上 void
* 建構物件時要使用 "new" 關鍵字
> 執行哪一個建構式,依照實例化時給定哪一種型態的引數而決定
* 預設建構式 (Default constructor):公開且無參數
範例:


#### 方法 (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成員

```java=
class Ball {
double radius;
static final double PI = 3.141596;
...
}
```
被宣告為static的成員,不會讓個別物件擁有,而是屬於類別,如上定義後,如果建立多個Ball物件,每個Ball物件只會各自擁有radius

* 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:


範例2:(呼叫其他類別的類別方法)


範例:
```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:


如果宣告的是基本型態參數,則呼叫方法時所給定的引數,會複製一份給參數;
如果宣告的是物件型態,則呼叫方法時所給定的物件,會被參數參考
範例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();
}
}
```

### 類別方法的傳回值
* 使用「return」關鍵字
* 傳回值的型態需要與方法宣告的傳回值型態相同
範例1:(無傳回值)

範例2:(有傳回值)


範例3:(有傳回值)


範例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)**
範例:


### 類別變數和變數範圍
* Java語言的變數分為類別的成員變數、方法參數和區域變數
* static + 成員變數 >> 類別變數
>>不需要伴隨物件,自己就有意義了
1. 區域變數範圍:在方法內宣告的變數,只能在程式碼後使用(不包括宣告前),在方法外的程式碼並無法存取此變數。
2. 方法參數範圍:傳入方法的參數變數範圍是整個方法的程式區塊,在方法外的程式碼並無法存取。
3. 成員變數範圍:不論是static的類別變數或是沒有宣告static,整個類別的程式碼都可以存取此變數。

範例:


範例:


### 遞迴的階層函數(Recursive)
* 遞迴:一個問題的內涵是由本身所定義
1. 遞迴方法在每次呼叫時,都可以使問題範圍逐漸縮小
2. 遞迴方法需要擁有終止條件,以便結束的執行
範例:


### Math數學類別的類別方法
* 在呼叫方法時需要指明類別Math

範例:

