---
# System prepended metadata

title: CMoney菁英軟體工程師訓練營第四屆
tags: [java]

---

CMoney菁英軟體工程師訓練營第四屆
===
## 2/25(day1)
### 額外
自動化玩具 ifttt、workflow
design pattern [非關語言: 設計模式](https://openhome.cc/Gossip/DesignPattern/)

### 命名規則
[命名規則參閱](https://www.javaworld.com.tw/jute/post/view?bid=20&id=27897&sty=1&tpg=1&age=0)
Project name 大寫起頭 駝峰式命名
package name 全小寫命名
Class name 大寫開頭 駝峰命名
variable, function name 小寫非數字開頭，駝峰式命名
宣告為final的變數（不可更動值）則全部大寫
### 變數
小數點預設為double
```java=
float f = 3.0f;
```
```java=
int num1, num2;
num1 = num2 = 0;
```
宣告連續變數，程式一律都是右邊開始執行
### 進制轉換
2->10
10->2
...
### 字元表示法
ASCII
java以Unicode存放char並且是2byte，所以可以存放中文字
### 強制轉型必要性
省略不必要的位數，過濾資料
```java=
float f = (int)3.66666;
System.out.println(f);
// 3.0
```
### 基本資料型態＆參照資料型態
java的基本資料型態包含int(4)、float(4)、boolean(1)、char(2)、double(8)、short(2)、long(8)、byte(1)*(括號內為byte數)*

當宣告基本資料型態變數時，是宣告一個標籤，標籤的位址存放基本資料型態變數的值；而當宣告一個參照資料型態，同樣宣告一個標籤，此標籤存放的值為這個==物件實體的位址==。

## 2/26(day2)
### 格式化字串
```java=
float f = 1.3333f;
System.out.printf("%.2f", f);
// 1.33
```
### if/else判斷
綜合所得税＆累進稅率計算（不同級距採if/else if方式）
#### & and &&
& 表示前後都要判斷
&& 若前面的判斷為false，則不需要判斷後面的判斷式，可以省判斷
| and || 也是同樣機制
```java=
// &&
int a = 80;
boolean c = true;
boolean d = false;
if(a >= 80 && (c = d)){
    ...
}
```
### switch case
### 算術指定運算子
需考量優先級
++ 與 小括號 同級別，故從左而右算
```java=
a += 1;
a++; // 先給後加
++a; // 先加後給
```
```java=
int a = 1;
int b = 0;
b = a++;
// a = 2 
// b = 1
```
```java=
int a = 1;
int b = 0;
b = ++a;
// a = 2 
// b = 2
```
```java=
int a = 1;
int b = 0;
b = a++ + ++a; // 1 + 3 
// a = 3
// b = 4
```
```java=
int c = 0;
int b = 0;
while(c < 3){
    b += ++c;
}
System.out.println(b + " " + c);
// 6 3
```
```java=
int c = 0;
int b = 0;
while(c < 3){
    b += c++;
}
System.out.println(b + " " + c);
// 3 3
```
### 進制轉換
10 -> 2
2 -> 8 將二進制3數為一組
2 -> 16 將二進制4數為一組

## 2/27(day3)
### while / for 
可於迴圈中加入變數當作計數器，用以計算迴圈重複的次數。
### do while
```java=
Scanner scanner = new Scanner(System.in);
int n;
do{
    n = scanner.nextInt();
}while(n != -1);
```
#### 星狀圖
各式圖形、倒三角、直角三角、等腰三角、菱形...
1. 空心平行四邊形
```java=
int n = scanner.nextInt();
for(int i = 1; i <= n; i++){
    // 做空格
    for(int j = 0; j < n - i; j++){
        System.out.print(" ");
    }
    for(int j = 1; j <= n; j++){
        if(i > 1 && i < n && j > 1 && j < n){
            System.out.print(" ");
        }else{
            System.out.print("*");
        }
    }
    System.out.println();
}
```
2. 實心菱形（兩塊）
```java=
//上半塊
for(int i = 1; i <= n; i++){
    for(int j = 1; j <= n-i; j++){
        System.out.print(" ");
    }
    for(int j = 1; j <= 2*i-1; j++){
        System.out.print("*");
    }
    System.out.println();
    }
//下半塊
for(int i = n+1; i <= 2*n-1; i++){
    for(int j = 1; j <= i-n; j++){
        System.out.print(" ");
    }
    for(int j = 1; j <= 4*n-1-2*i; j++){
        System.out.print("*");
    }
    System.out.println();
}
```
3. 實心菱形（一塊）
:::info
==絕對值==想法實作
:::
```java=
int n = scanner.nextInt();
for(int i = 1; i <= 2*n-1; i++){
    for(int j = 1; j <= (int)Math.abs(n-i) ; j++){
        System.out.print(" ");
    }
    for(int j = 1; j <= (2*n-1)-(int)Math.abs(2*(i-n)); j++){
        System.out.print("*");
    }
    System.out.println();
}
```
4. 空心菱形
```java=
int n = scanner.nextInt();
for(int i = 1; i <= 2*n-1; i++){
    // 左方空白(倒直角三角、直角三角)
    for(int j = 1; j <= (int)Math.abs(n-i) ; j++){
        System.out.print(" ");
    }
    System.out.print("*"); // 左方星號
    // 第2到第2*n-1層
    // 中間空白部分
    // 以正中為主分割兩邊
    // 左方空白數從0到n-2
    // (n-2)-Math.abs(i-n) 層數距離n越遠,空白數越少,故為減數
    // 正中空白數固定1個
    // 右方空白數與左方同樣,乘2即可
    if(i > 1 && i < 2*n-1){
        for(int j = 0; j < 2*((n-2)-Math.abs(i-n))+1; j++){
            System.out.print(" ");
        }
        System.out.print("*"); //右方星號
    }
    System.out.println();
    }
```

## 3/4(day4)
### 陣列
是一個參考資料型態，會於heap當中創造連續記憶體空間，用以存放型態相同的資料，所以存放的地址即為“第1個元素的位置(index = 0)”
所以array在搜尋資料的速度很快，直接加上“第幾筆*宣告的資料結構大小”，即為第幾筆資料的記憶體位址。
```java=
int nums[] = new int[5];
// 有一個叫做 nums 的標籤
// stack存放的值為new出的實體的記憶體空間位址
// 這個值也同樣是 陣列第一個元素的記憶體位址
```
:::info
**nums 與 nums[0]的差異**
nums -> addr's value (整個陣列)
nums[0] -> value(stored in addr) (值)
:::
==當我們創建了一個**參考資料型態**的陣列，每個陣列值存放的是這群實體各自的記憶體位址==
```java=
// example
NewClass[] nc = new NewClass[5];
// nc的stack 存放 new NewClass()建立的實體的記憶體位址
System.out.println(nc); // [Lcmoneyclass.NewClass;@1540e19d
System.out.println(nc[0]); // null
// 仍須各自new出新的記憶體空間來指派給各自的值
// 並非同時new出多個實體
```

## 3/5(day5)
### 函式function
類似功能寫成函式，更動的數值設計為變數。
#### 靜態方法static
不需類別物件實體即可使用的方法
#### 技巧：利用return將void函式強制回傳
可以適用於多層巢狀迴圈的打斷(將巢狀迴圈包裹於void函式中)，因為可能在內部迴圈結束時即break出此巢狀迴圈，但break只能跳出最近的迴圈，無法跳出外部的迴圈。
#### 傳值呼叫
![](https://drive.google.com/uc?export=view&id=1qDlMjxZ90SnNzNM6dywva8MAdel1g_HM)
```java=
int a[] = new int[2];
a[0] = 1;
a[1] = 2;
func(a);
System.out.println(a[0]);
// 5
```
```java=
public static void func(int b[]){
    // 新開了一個b[]的標籤，存放傳入的a陣列地址
    // 所以更動此地址所指的記憶體空間
    // 同樣會影響到原有a陣列
    b[0] = 5;
}
```

## 3/6(day6)
### 排序
1. bubble sort
```java=
public static void bubbleSort(int[] arr){
    // 找出第幾大的數字 第1次第1大 第2次第2大...
    for(int i = 0; i < arr.length-1; i++){
        // 檢查剩下的每一元素，如果較大則交換
        // 跑完 即 將當次最大數往右排
        for(int j = 0; j < arr.length-1-i; j++){
            if(arr[j] > arr[j+1]){
                swap(arr, j, j+1);
            }
        }
    }
}
```
2. insertion sort
3. selection sort
##### 問：利用XOR來實現變數互換?
[如何交換兩個變數，而不動用第三個變數?](http://clifflin123456.pixnet.net/blog/post/44902733-%E5%A6%82%E4%BD%95%E4%BA%A4%E6%8F%9B%E5%85%A9%E5%80%8B%E8%AE%8A%E6%95%B8%EF%BC%8C%E8%80%8C%E4%B8%8D%E5%8B%95%E7%94%A8%E7%AC%AC%E4%B8%89%E5%80%8B%E8%AE%8A%E6%95%B8%3F-%E5%88%A9)
主要想法來自於兩個變數的二進制，不需要額外的變數即可達到變數交換的效果。
> example : 
> x = 5 = 101
> y = 6 = 110
> > 兩數使用XOR來做交換
> x = x XOR y = 011 = 3
> y = x XOR y = 101 = 5
> x = x XOR y = 110 = 6
> > > x = 6
> > > y = 5 
### 隨機數
利用Math.random()函數可用來設定隨機數字。
```java=
Math.random() // return a float between 0 to 1
```
* 實例應用：選取一個範圍中的隨機數
想法：因為Math.random()會回傳0~1之間的隨機小數，0與1之間的間隔為1，要將此間隔擴大至所需的範圍+1，所以乘以範圍再加上最小值進行平移。
```java=
public static int randomNum(int min, int max){
    return (int)(Math.random()*(max-min+1))+min;
}
```
* 實例應用：創建一個儲存值亂序的陣列
想法：首先設定一個內容值為其索引值的陣列，接著將針對其中第i個值，從剩下(num-i)個值中隨機抽取出一個做調換。
```java=
public static int[] getRandArr(int num){
    int[] randArr = new int[num];
    // set value
    for(int i = 0; i < num; i++){
        randArr[i] = i;
    }
    // 第 i 張牌與後方隨機(num-i)張牌互換
    for(int i = 0; i < num; i++){
        swap(randArr, i, getRandNum(i+1, num));
    }
    return randArr;
}
```
### 課堂練習
1. 成績排序(by座號)(by成績)
2. 排亂順序輸出
3. 撲克牌發牌(不重複值亂序陣列)

## 3/7(day7)
### 多維陣列
在java中，是以一個一維陣列的各個元素各自指向其他的一維陣列。表示第一個一維陣列存放各自指向的一維陣列的位址。
```java=
// 先開一個大小為3的一維陣列
// 存放大小為4的一維陣列的位址
// 大小為4的陣列存放實際的值
int[][] array = new int[3][4];
```
在記憶體操控方面會相較C語言的其中一種方式("直接開一個要的大小"&與"java相同機制")更為靈活，能夠配置空間較小的多個陣列實體。
#### 陣列記憶體控制
* 倍增一維陣列存放空間
```java=
public static void main(String[] args){
    int[] nums = new int[5];
}
public static int[] doubleArr(int[] arr){
    int[] tmpArr = new int[arr.length*2];
    for(int i = 0; i < arr.length; i++){
        tmpArr[i] = arr[i];
    }
    // arr = tmpArr; 
    // 這行表示將arr陣列指向新開的tmpArr陣列位址
    // 但此時nums仍指向原有的nums陣列實體
    return tmpArr; 
}
```
:::info
Q:**為什麼需要將欲改變大小的陣列位址回傳？傳入陣列來做操作不是就是針對傳入地址的陣列來做改變了嗎？**
A:當傳入一個陣列，會在stack中新增一個標籤(arr)來指向原有的陣列位址，而我們需要一個新的2倍大小的陣列時，必須在heap中新開一個兩倍大小的陣列實體，並用新的標籤(tmpArr)去指向這個實體，再將原有的數值一一複製過去，最後回傳兩倍大小陣列實體的位址回去。
如果只將新開的標籤(tmpArr)所存的位址重新指派給原先指向陣列的標籤(arr)，則原先的標籤(nums)所指向的位址仍非兩倍大小的陣列實體。(如圖一)
(圖一)![](https://drive.google.com/uc?export=view&id=1J1etN-SbtOjDfwHhL5l8MaSW9w8zGy5A)
:::
* 倍增二維陣列存放空間(第二維其中一個)
假如想要只倍增nums[2][2]的第二維空間大小，則不需要將陣列位址回傳也可以。
原因在於，當我們傳入一個想要倍增第二維空間大小的二維陣列，我們不需要針對第一維存放的位址做任何的改變，只要創建出新的兩倍大小的一維陣列來將數值重新指派即可。
如圖二的步驟。
:::success
==step1==：原先的nums標籤指向一個大小為2的一維陣列實體，分別存放一個大小為2的一維陣列地址。
==step2==：將欲倍增的陣列傳入，會先宣告一個arr的二維陣列標籤指向nums所指向的陣列實體。
==step3==：再宣告一個一維陣列標籤tmpArr來指向兩倍大小的新陣列實體。
==step4==：分別將原有陣列的值指派給倍增的陣列。
==step5==：最後將倍增大小的陣列地址指派給欲擴增的的陣列。(原先指向的陣列實體，會交由gc機制來做回收。)
:::
(圖二)![](https://drive.google.com/uc?export=view&id=1-3nCouO2x8JlBARt-niZzMLHz0VNiP7e)
```java=
public static void main(String[] args){
    int[][] nums = new int[2][2];
}
public static void doubleArrr(int arr[][]){
    int[] tmpArr = new int[arr[0].length*2];
    for(int i = 0; i < arr[0].length; i++){
        tmpArr[i] = arr[0][i];
    }
    arr[0] = tmpArr;
}
```
* 倍增二維陣列存放空間(全部)(假設每個大小都相同)(2x2->4x4->8x8...)
==想法==：直接開一個，再將值複製過去。
```java=
public static void main(String[] args){
    int[][] nums = new int[2][2];
}
public static int[][] doubleArrrr(int[][] arr){
    int[][] tmpArr = new int[arr.length*2][arr[0].length*2];
    for(int i = 0; i < arr.length; i++){
        for(int j = 0; j < arr[0].length; j++){
            tmpArr[i][j] = arr[i][j];
        }
    }
    return tmpArr;
}
```
* 倍增二維陣列存放空間(第一維)
==想法==：將第一維擴大，再將擴大的地方new出新的空間asign回去。不然第一維擴大的部分沒有新的空間指向他。
```java=
public static int[][] doubleArr(int[][] arr){
    int[][] tmpArr = new int[arr.length*2][];
    for(int i = 0; i < arr.length; i++){
        tmpArr[i] = arr[i];
    }
    for(int i = arr.length; i < arr.length*2; i++){
        // 倍增的部分再new出新的實體給他
        tmpArr[i] = new int[arr[0].length];
    }
    return tmpArr;
}
```

## 3/8(day8)
* 課中練習檢討：擴增陣列存放學生資料並排序
* 額外練習講解：1A2B猜數字遊戲(手動猜&電腦猜)
### 1A2B猜數字(手動猜)
==想法==：問題拆解成許多小問題，像是需要check每一次有幾A幾B、將數值各個位數以陣列存放、判斷是否有重複數字的四位數字...
### 1A2B猜數字(電腦猜)
==想法==：每次先猜1234，或是接著猜5678，當有第一次的AB數量時，從所有可能的答案中找出同樣AB數量的答案，再從這些篩選過的答案中去隨機猜，每次都去核對AB數量，再次剔除掉AB數量不同的答案，使隨機猜的範圍逐漸變小，重複直到猜中。

### 練習：讀取字串並計算字串數量
#### 利用array實作dictionary
dictionary可以關鍵字來查詢特定位置的資料，在其他語言中，可以透過給予key值來查找這個key值身上的資料，在此以array的方式來實作。
==實作想法==：
```java=
// 陣列初始大小
String[] strings = new String[2];
// 陣列實際存有值的數量
int count = 0;
// 關鍵字陣列(不重複)
String[] dictionary = new String[2];
int[] nums = new int[2]; // 紀錄每個關鍵字的數量

int j;
int dictionaryCount = 0; // 記錄dictionary中值的數量
for(int i = 0; i < count; i++){
    for(j = 0; j < dictionaryCount; j++){
        if(dictionary[j].equals(strings[i])){
            nums[j]++;
            break;
        }
    }
    // 表示有新的字典關鍵字需要加入
    if(j == dictionaryCount){
        dictionary[j] = strings[i];
        nums[j]++; // 加入的關鍵字數量設為1
        dictionaryCount++;
    }
    // 倍增陣列存放空間
    if(dictionaryCount == dictionary.length){
        dictionary = doubleStringArr(dictionary);
        nums = doubleIntArr(nums);
    }
}
```
## 3/11(day9)
* test2
### 字串
* ASCII code
* 字元 & int 互換
* String Pool
在heap中有一個特別的空間(String Pool)，用來存放所有傳入字串的地址。
ex:
String Pool中存有"123"這個字串
```java=
String a = "123";
String b = "1" + "23";
System.out.println(a == b); // true
```
```java=
String a = "123";
String b = new String("123");
System.out.println(a == b); // false
```
所以當要比較兩個字串值是否相等，必須使用String.equal()方法。
### 字串物件的方法
* split()
給予切割字元，切出一個string array
* substring(start, end)
切出起始位置到結束位置-1的值，總計(end - start)字元。
* 其他 可參閱 7.3 ppt or 上網查
### 遞迴
#### 費氏數列(遞迴)(非遞迴)寫法

==*遞迴版本*==
```java=
public static int fibonacciByRecursion(int num){
if(num == 1) return 1;
if(num == 0) return 0;
return fibonacciByRecursion(num-1) + fibonacciByRecursion(num-2);
}
```
==*非遞迴版本*==
```java=
public static int fibonacciByForLoop(int num){
    // 陣列大小為費氏數+1的原因在於 f(0)=0
    // 當想要求f(10)時，實際上需要10+1個空間大小
    int[] nums = new int[num+1];
    // 藉由陣列來存放每個費氏數的值
    for(int i = 0; i < num+1; i++){
        if(i == 1) nums[i] = 1;
        if(i == 0) nums[i] = 0;
        if(i > 1){
            nums[i] = nums[i-1] + nums[i-2];
        }
    }
    return nums[num];
}
```
#### 河內塔
有n個盤子和三座塔(A、B、C)，需要將盤子從A塔移到C塔，其中每個盤子上都有各自的編號，移動的過程必須符合以下規定：一次動一個盤子，編號大的盤子不能疊在編號小的盤子上。
==遞迴想法==：
主要分成三個步驟：
步驟一：首先將(n-1)個盤子從A塔移動至B塔。
步驟二：再將剩下的那個最大盤子從A塔移動至C塔。
步驟三：最後將B塔的(n-1)個盤子從B塔移動至C塔。
base case：當只有1個盤子時，印出移動過程。
```java=
public static void hanoi(int plate, char start, char terminal, char tmp){
    // base case
    if(plate == 1){
        System.out.println("from " + start + " to " + terminal);
        return;
    }
    hanoi(plate-1, start, tmp, terminal); // step 1
    hanoi(1, start, terminal, tmp); // step 2
    hanoi(plate-1, tmp, terminal, start); // step 3
}
```
## 3/12(day10)
### 函式多載(overloading)
相同函式名稱可以同時存在，但給予的參數必須不同，且回傳值的類型必須相同。
舉例：swap()方法，用來交換一維或是二維陣列，傳入不同維但可以同樣實現交換的方法。
### 物件導向
任何物件都在類別之下，身上具有屬性及方法，與一般結構式語言(C/C++)不同，缺點可能在於效能會差一點，但好處在於易於程式設計。
#### static靜態方法
與類別相同層級，不需要有類別的實體即可使用的屬性或方法。
#### 封裝(encapsulation)
封裝性適用於將設計好的類別給別人使用時，給予不同的權限設計，用來避免設計好的類別內容遭人更改。
* public
* private
* protected
* default

但可藉由setter/getter來間接存取修改屬性值。
#### 建構子(constructor)
當物件實體產生時，會自動執行的方法，用來將傳入參數指派給物件身上的屬性。當不寫建構子時，會自動產生一個空的建構子。若當創建了建構子時，空的建構子會被刪掉，若有空建構子的需求，必須再自行創建。
建構子也有overloading的概念，所以可以創建多個不同參數的建構子。

*若要傳入陣列當作參數，不要將空間在類別中new出來，在建構子中設計。*
#### this關鍵字
this關鍵字在執行時是指現在這個類別操作的物件實體，而在類別中寫到這個關鍵字則是表示這個類別本身，所以我們可以將傳入參數帶入此物件身上的屬性。
```java=
/* MyClass.java */
public class Myclass(){
    int width;
    int height;
    // 建構子
    public MyClass(int w, int h){
        this.width = w;
        this.height = h;
    }
}
```
```java=
public class Tester(){
    public static void main(String[] args){
        MyClass mc = new MyClass(5, 3);
        System.out.println(mc.width); // 5
        System.out.println(mc.height); // 3
    }
}
```
#### toString()
當使用System.out.print()方法時，會將傳入的物件，呼叫他身上toString()方法，將非String的值，回傳成String，所以可以修改身上的toString()方法，來將物件想要印出的內容印出，否則會印出此物件的地址。
```java=
/* main */
public class Main{
    public static void main(String[] args){
        NewClass nc = new NewClass();
        System.out.println(nc); // nc地址
    }
}
```
```java=
/* NewClass */
public class NewClass{
    /* attributes...
     * constructor...
     * */
    public String toString(){
        String strings;
        strings = attribute1 + " " + attribute2 + " ";
        return strings;
    }
}
```
將我們在類別中設定自己的toString()方法，實際上是複寫(overide)了object最上層類別的方法，就可以印出自己想要輸出的東西。
#### 物件陣列
```java=
Student[] students = new Student[10];
// 創建出一個10格的陣列空間想要用來存放學生物件的地址
// (內容都為null，還沒有學生物件的實體)
students[0] = new Student("kj", "大象", 100, 98, 99);
```
如下圖所示：(實際記憶體配置狀況)
![實際記憶體配置狀況](https://drive.google.com/uc?export=view&id=1qRsYfZOcinZppGUeB5-16Gyn0fWlBJdd)
所以當我們要存取或是寫入類別物件陣列的元素時，必須先將他new出來。

## 3/13(day11)
* 學生類別實作講解
* 加入學生陣列類別改寫
將分工細分
類別設計中，可以在類別中宣告自己的類別，也能夠在方法中傳入自己的類別，只是在設計上要小心。
而在封裝等級上，若如入自己類別的參數，能夠直接取得private的參數，而不需要透過getXXX()的方法，因為類別相同而層級相同。
```java=
public class Rectangle(){
    int width;
    int height;
    public Rectangle(int w, int h){
        this.width = w;
        this.height = h;
    }
    // 比較兩長方形大小
    public int compare(Rectangle rectangle){
        if(this.getArea() > rectangle.getArea()){
            return 1;
        }else return 0;
    }
}
```
* 出牌遊戲實作
* Uno

## 3/14(day12)
* 出牌遊戲實作
* Uno
### String.next()與String.nextLine()的差別

## 3/15(day13)
### 課堂實作講解
#### static
==好用，但不可濫用。==
在類別實體建成之前就開了一個空間給static屬性或方法，當我有多個類別實體，全部都共用同一個static空間，所以若是其中一個物件更改了static屬性或方法，同樣類別的所有物件的static屬性或方法都會被修改。
通常使用於不會更動的常數屬性或方法。
### final
不可更動的屬性，必須在建立時即初始化。

## 3/18(day14)
* 測驗3
* 講解測驗3

## 3/19(day15)
### 繼承
取得父類別屬性在類別中採用super關鍵字來表示父類別。
父類別建構子會比子類別建構子優先執行，而當父類別具有不為空的建構子時，必須在子類別的建構子中呼叫父類別建構子，將父類別建構子的事情先做完，才會做子類別的建構子。
所以==父類別建構子必須寫在子類別建構子的第一行，確保父類別要做的事情都先做完。==
### 繼承的屬性
當繼承自父類別的屬性要取用時，一般都以super.getter()方法來做取用，而當子類別中也有同名屬性時，父類別的屬性會隱藏，但仍佔有記憶體空間，在調用時以this和super來做區別。
### Override
當我們複寫方法時，回傳值的型態受到規範，也就是說可以回傳原先類別，或是繼承自原先類別的子類別型態，因為子類別繼承自父類別，應該可以達成所有父類別能夠完成的事情。
而複寫(Override)與多載(Overloading)的差別在於複寫是將父類別的方法來做改寫，一般會加上"@Override"來告知系統；而多載是相同名稱的方法具有不同的傳入參數。
***以String.toString()來做範例***
```java=
@Override
public String toString(){
    return "這是Override";
}
```
```java=
public String toString(int num){
    return "這是Overloading" + num;
}
```
## 3/20(day16)
### Object類別
所有物件都會繼承的父類別，在java中也是唯一一個沒有父類別的類別。當一個類別沒有繼承任何類別時，系統會自動繼承Object類別。
### 多型
父類別物件可以以子類別的物件實體來儲存，因為子類別的物件實體中必定包含父類別物件的實體。
#### downcasting
```java=
Shape[] shapes = new Shape[2];
shapes[0] = new Rectangle(3, 5);
```
#### 多型應用範例
```java=
// shape父類別
Shape[] shapes = new Shape[5];
shapes[0] = new Rectangle(3, 5);
shapes[1] = new Circle(5);
shapes[2] = new Rectangle(1, 7);
shapes[3] = new Circle(3);
shapes[4] = new Rectangle(7, 9);
```

## 3/21(day17)
* 生態系實作
## 3/22(day18)
### 泛型
在Java中已經先幫我們實作出一些資料結構，可以直接使用身上的方法，而不需要自己去寫doubleArr()、getCount()之類的方法。
以ArrayList來做說明，<>在這個diamond符號中的類別，表示這個ArrayList中能夠存放的類別，
```java=
ArrayList<Integer> nums = new ArrayList<>();
nums.add(3);
nums.add(2);
nums.add(1);
```
### 資料結構(array、linkedList)
* array
連續記憶體空間，
* linkedList
不需連續的記憶體空間
```java=
// 實作
// 包含 add()、remove()、get()、insert()、size()方法
```
## 3/25(day19)
* test4
筆試：記憶體管理、進制轉換、手寫程式碼(卡牌)
上機：形狀類別 & 高鐵購票系統
## 3/26(day20)
* test4檢討
### 檔案管理
* BufferedWriter
* BufferedReader
> *增加效能的作法為減少與外面檔案io的次數*

java中採用==buffer緩衝區==的做法增加效能，先將一定大小的資料流存進緩衝區，等到需要用到時才從緩衝區將資料拉進來處理，可以減少與外頭檔案io的次數。*緩衝區在記憶體中、外頭檔案在硬碟中*
::: warning
記得每次開啟檔案讀取或寫入完成後都要將檔案關閉。
:::
***在實際使用時，通常都是將檔名傳入寫/讀檔案的function，在function中新建BufferedWriter、BufferedReader來做處理。
而在檔案存讀取的時候，盡量先將資料先存入預想的資料結構中，若是之後還有處理檔案的需求則能夠直接使用這些資料，待所有處理都結束時才將檔案寫入。***

## 3/27(day21)
### 檔案管理系統練習
* 學生資訊系統
* 捷運系統
## 3/28(day22)
* 捷運系統
## 3/29(day23)
* 捷運系統
## 4/1(day24)
* test_5
### 介面(Interface)
其中只能有常數以及抽象方法，方法教給時做這個界面的類別來實作。較常使用於責任歸屬的區分上，介面能夠實現多種抽象方法，讓實作同一個介面的類別能夠達成不同的方法。
interface : 
```java=

```
* slime史萊姆戰鬥
## 4/2(day25)
### 內部類別
若是此類別只服務特定的類別，例如LinkedList中的Node，可以將此類別寫在LinkedList類別其中。需要上層類別的實體才能建構出此內部類別的實體。
### 靜態內部類別
若有需要直接取得內部類別，可以將內部類別設置為靜態方法，可以讓其不需要外部類別實體即可創建。
### 匿名內部類別
當我們需要一個類別來實現實作介面，但此類別只被使用到一次，我們可以直接在需要使用它的地方，創建出一個匿名類別實體直接實現介面的實作，但不需要直接開一個新的類別給他。

* 進階史萊姆戰鬥

## 4/3(day26)
* 進階史萊姆戰鬥
* LinkedList講解 & 技巧

***ArrayList & LinkedList差別以及優缺***
* ArrayList 
查找快
* Linkedist

## 4/8(day27)
* test6
* 加總計算(遞迴、讀寫檔練習)

## 4/9(day28)
### java動畫與繪圖
### Adapter
是一個實現了多個介面的類別，可以繼承這個類別來選擇自己想要改寫的介面方法，才不需要通通實現。(如果自己實現這些介面會讓整體程式碼變得太過雜亂)
### 共同類別存放共通屬性
圖片的座標、繪製出來的方法
:::info
**若將圖片檔存在共通的類別呢？**
*共通的類別不會存圖檔，可以交給繼承此類別的子類別來存
若有許多相同怪物使用同一張圖 -> 可以採用static來存圖片
但若是有許多不同的怪物，則需要有不同的類別來各自存放，但行動都一樣，卻需要開這麼多類別...
比較好的做法是
將圖片共同存入一個資源庫
只要有使用到圖片的時候，就將存放圖片的位置回傳*
:::
## 4/10(day29)
* java動畫與繪圖
* 隨機生成 & 碰撞 & 射擊
* KeyEvent類別用法
## 4/11(day30)
### 解決ImageIO重複讀取檔案效能問題
* 可以採用static(但換圖會出問題)
若是同一個角色類別會運用到不同張圖，則會將圖一起換掉。
* 資源管理器(類別)
這個類別中會存放共同的資源，
## 4/12(day31)
* RPG製作練習
## 4/15(day32)
* abstract class 抽象類別
## 4/16(day33)
### 版本控制
* BitBucket & SourceTree
## 4/17(day34)
* 期中專題
## 4/18(day35)
### 例外處理
* Error
嚴重的系統錯誤，通常不處理，直接拋出錯誤訊息。
* Exception
通常不為系統所發生的錯誤，多數來自變數或執行上才發生的例外。
#### try...catch...finally
用來處理有可能發生例外的狀況。
```java=
try{
    // (預計要做的事情)
    // 有可能會發生例外的狀況
    // 當狀況發生時，直接拋出例外
    // 拋出例外程式碼以下的程式碼不會被執行到
} catch(MyException e){
    // 當接到此例外時，做處理
} finally{
    // 無論如何都會執行的部分
    // 即便在try或catch之中已經有return
    // 同樣會執行
}
```
* Example
```java=
try{
    System.out.println("try");
    throw SomeException;
    System.out.println("not reach");
} catch(SomeException e){
    System.out.println("deal with exception");
    return 0;
} finally{
    System.out.println("finally");
    return 1;
}
// try
// deal with exception
// finally
// return回去的值 "1"
```
:::info
**多型 可能會遇到狀況**
* 當在父類別的方法中嘗試拋出例外，在子類別的方法中，若是改寫了父類別的此方法，若是同樣可能會拋出例外，沒辦法去拋出父類別設定的例外層級以上的例外，只能拋出父類別拋出例外層級之下的例外(繼承自父類別例外的子例外)。
* 原因在於若有多個子類別去改寫這些方法，可能會拋出不同的例外，若是此例外不屬於父類別例外的子例外，則無法接受設定的處理，==不在父類別例外的處理範圍中了==。
:::
* Example
```java=
// 父類別
public class Shape {
    // 自己設計的例外
    public class SomeException extends Exception{
    public SomeException(String msg){
        super(msg);
    }
    // 父類別中可能會拋出例外的方法
    public int getArea() throws SomeException{
        System.out.println("try");
        throw new SomeException("there is something wrong");
    }
}
```
```java=
// 子類別
public class Rectangle extends Shape{
    // 改寫父類別中可能會拋出例外的方法
    // 可以不拋出，若要拋出
    // 必須拋出父類別拋出的例外層級以下或相同的例外
    @Override
    public int getArea() throws SomeException{
        throw new SomeException("例外的子類別");
    }
    // 拋出父類別可能拋出層級的例外會報錯
    // @Override
    // public int getArea() throws Exception{
    //     throw new Exception("");
    // }
}    
```
## 4/19(day36)
* 遊戲專題
## 4/22(day37)
### 測驗8講解
StringArrayList與StringLinkedList以介面(Iterator)及抽象類別(List)實作，並加入concat()方法設計。
### 泛型
只能夠將型別宣告為參考資料型態，不能宣告為基本基料型態。
#### 以泛型實作LinkedList
* 自己練習
### Stack
:::info 
一般程式執行時，即是創建了許多系統的stack來記錄執行的順序以及回傳的地址。
而遞迴之所以慢，就是創建了許多stack，等到執行到終止條件時，逐漸將回傳值一個個pop()回來。 
:::
stack中主要包含push()、pop()兩種方法
push()：將資料加入stack中。
pop()：將頂端資料取出回傳，並從stack中移除。
==額外方法==
peek()：傳回頂端資料，但不將資料從stack中移除。
* 可實際應用於 "上一頁下一頁"的機制
* 走迷宮練習

```java=
// 迷宮路徑搜尋
// 
```
## 4/23(day38)
* 遊戲專題
## 4/24(day39)
* 期中專題階段發表
(待補)
1. 需要修改的部分...

共通問題：
1. 扣緊故事
2. 遊戲說明
3. 分工詳細說明
4. 簡報前後呼應，要有完整性
## 4/25(day40)
* 遊戲專題
## 4/26(day41)
* 遊戲專題
## 4/29(day42)
* test9
### Queue
通常會應用於"執行緒"相關。
:::info
例如：購票系統 or 網路request
當許多的request進入到系統中，不可以出現超賣票卷的情況，因此只要加進queue之中再慢慢處理即可，後續超過的部分就不處理。
:::
#### queue處理方式
以ArrayList來實現會有front和rear重疊的情況，無法新增值，但queue卻為空的情形。
* 環狀queue來處理

## 4/30(day43)
### 雜湊Hashing
查找對應內容速度最快：O(1)
經由hash公式換算出對應的記憶體位置，直接去記憶體位置拿資料。
#### 理想Hashing
#### Hashing 碰撞 & 溢出
:::info
討論
* 如何選擇 hash function(降低碰撞)
* 如何處理 Overflow)
* 如何設定 hash table 的大小
:::
#### 數位簽章
* Token
當使用者傳送帳號密碼給伺服器端，伺服器端會將id、時間戳記以及傳送request後拿到的hash值，打包成一個Token，回傳給使用者，讓使用者接下來不需要再打密碼就能夠使用服務，只要回傳token，伺服器端就能確認使用者是本人。
## 5/2(day44)
* 遊戲專題 demo day
## 5/3(day45)
* 遊戲專題
## 5/6(day46)
* Test10 - Queue & Stack 實作應用
* Android Studio 安裝
## 5/7(day47)
### Android Studio
package name是在googleplay商店上架用來識別有無重複的依據。也同樣是專案在電腦中的檔案架構。
### activity簡介與生命週期
![](https://i.imgur.com/TUqzuzJ.png)

### XML檔案與LinearLayout
是一種文本格式，跟json相同。Andriod Studio會依據此XML文件來生成對應的程式碼。
在Android中所有的元件都是View的子類別(比較像是Component的概念)，都會在一個Container中。
### Margin & Padding
Margin與元件的外間距
Padding與元件的內間距

### Weight
依據所有元件的比重來分配自己在剩餘空間的大小
* weightSum
### Id
透過id來將java檔與xml文件做連結。

## 5/8(day48)
### Andriod Studio基礎元件

### Memory Leak 記憶體流失

## 5/9(day49)
### Json
#### JsonObject
#### JsonArray
### SharedPreference

## 5/10(day50)
* 遊戲專題
## 5/13(day51)
* test11 -  Android Studio 拉畫面 
## 5/14(day52)
* 遊戲專題
## 5/15(day53)
* 遊戲專題
* 期中發表彩排
## 5/16(day54)
* 最後衝刺
## 5/17(day55)
* 期中遊戲專題發表
## 5/20(day56)
* test12
### 二元搜尋法(binary search)
適用於已經排序好的陣列
:::info
要怎麼從雜亂數列中找到數？
視情況而定or直接找最快
:::
### 樹狀結構
### 二元樹
### AVL Tree
## 5/21(day57)
* 模擬面試
## 5/22(day58)
### 排序法 Sort
內部、外部排序
#### 各種搜尋法
* insertion sort
* selection sort
* quick sort
* merge sort
* * natual merge sort
切分出已經排好的片段，再將片段合併。
* heap sort
## 5/23(day59)
* natural merge sort實作
## 5/24(day60)
* natural merge sort實作
## 5/27(day61)
* test13
* 模擬面試
    * 話題不要發散，回答問題只給答案就好，對方有興趣再說明
    * 履歷寫到的點都需要跟應徵的工作有連結
### Shared Preference
用來儲存少量資料，紀錄應用程式的一些相關資訊。
```java=
private SharedPreferences sp;
sp = this.getSharedPreferences("DATA", MODE_PRIVATE);
// builder pattern 設計模式 回傳editor自己
// 寫入資料
sp.edit()
        .putString("DATA_NAME", "test")
        .putInt("DATA_AGE", 15)
        .commit(); 
        // commit(直接同步寫入) or apply(找時機寫入) 才會將資料寫入
// 取資料(第2個參數是自己給的預設值)
// 確保程式不會出錯，一定會有取到值
int i = sp.getInt("DATA_AGE", 0);
```
### 多執行緒(Thread)
電腦來回切換正在處理的程序(process)，做一點點後切換。
通常process死亡後，其下的thread都會跟著死亡。
:::info
*為何網路連線都需要採用多執行緒？*
有網路不好的情況，若是只有單執行緒會造成程式直接卡死，會等待網路連線後才繼續執行程式。(UI會卡住)
需要採用多執行序分別負責網路連線以及UI控制的部分。
:::
## 5/28(day62)
### BuilderPattern(建造者模式)
用來處理建構子無法滿足所有使用情況時。
* 創建相同實體的builder
* 創建不同實體的builder
### Toast & AlertDialog
Toast會彈出視窗，顯示文字訊息一段時間。
AlertDialog繼承自Dialog類別，用來彈出可選擇使用選項按鈕的視窗等，
### 誰是臥底？畫面實作
* seekBar
* switch
* AlertDialog.builder
* LayoutInflator
## 5/29(day63)
### 頁面傳遞資訊
* Intent 傳遞值
* Bundle 打包成一包丟過去
* 序列化(sequentialable & parcelable)
### 改寫返回鍵
### 實現雙擊螢幕做特定事件
利用延遲與boolean來實現。
拉出類別以及介面來實現：
```java=
@Override
public void onBackPressed(){
    ClickedUtil.clicked(isClicked, new ClickedEventListener() {
        @Override
        public void singleClicked() {
            isClicked = true;
            Toast.makeText(MainActivity.this, "single clicked", Toast.LENGTH_SHORT).show();
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    isClicked = false;
                }
            }, 2000);
        }

        @Override
        public void doubleClicked() {
            Toast.makeText(MainActivity.this, "double clicked", Toast.LENGTH_SHORT).show();
            MainActivity.super.onBackPressed();
        }
    });
}
```
```java=
public interface ClickedEventListener {
    void singleClicked();
    void doubleClicked();
}

```
## 5/30(day64)
* 誰是臥底？實作
## 5/31(day65)
* 誰是臥底？實作
## 6/3(day66)
* test14
### RecyclerView
### Adapter Pattern
### Factory Pattern

## 6/4(day67)
### API
### GCP 環境建置
[GCP環境建置](https://hackmd.io/aBLvcH0HSHuD9HHUIXuzhg?both)
### Restful API
* GET
運用網址來取得資料(一般不用於傳遞具隱秘性的資料)
:::info
https://www.google.com/search?safe=off&client=firefox-b-d&q=jiejie&spell=1&sa=X&ved=0ahUKEwjv4ra6oc_iAhUtGKYKHX0rDOQQBQgrKAA&biw=1244&bih=681
* 裡面可以看到有些safe、client...的變數名稱，表示是採用get的方式來做資料傳遞
:::
* POST
* PUT
* DELETE
### CRUD
create、read、upload、delete
## 6/5(day68)
* 自主練習
## 6/6(day69)
* 自主練習
## 6/10(day70)
* Test_15(RecyclerView & JSON應用)
* 考試講解
## 6/11(day71)
### Android 連結api
* 連結"誰是臥底遊戲"？
採用"okhttp"此套件
[okhttp](https://github.com/square/okhttp)
### 網路連線功能封裝
## 6/12(day72)
### 拆分專案架構(以node.js)
### GET & POST
#### Get的方法
* params
* query
#### Post的方法
### CallBack function
[CallBack函式說明](http://fiend1120.pixnet.net/blog/post/196941375-callback-function)
## 6/13(day73)
### MongoDB建置
## 6/14(day74)
*  連接資料庫Api
## 6/17(day75)
* 會員註冊系統api撰寫
## 6/18(day76)
* 會員註冊系統api撰寫
## 6/19(day77)
* 會員註冊系統api撰寫
* 誰是臥底檢查
## 6/20(day78)
* Vue環境建置
## 6/21(day79)
* 期末專題提案
## 6/24(day80)
* 會員註冊&登入系統作業檢查
* API test16
## 6/25(day81)
* 期末專題討論
## 6/26(day82)
* 期末專題討論
## 6/27(day83)
* 期末專題討論
## 6/28(day84)
* Trello
* 專案開發技巧 看板方法
## 7/1(day85)
* 期末專題
## 7/2(day86)
* 加解密
    * MD5
        
    * RSA
        
    * SHA
        
* JWT (JSON Web Token)
## 7/3(day87)
### Heap Sort
* heap sort 一般使用場景
外部排序
## 7/4(day88)
* 期末專題
## 7/5(day89)
* 期末專題
## 7/8(day90)
* 期末專題
## 7/9(day91)
### 設計模式-觀察者模式
### 設計模式-狀態模式
### And Or 邏輯閘實現
## 7/10(day92)
* 期末專題
## 7/11(day93)
* 期末專題
## 7/12(day94)
* 期末專題
## 7/15(day95)
* 期末專題
## 7/16(day96)
* 期末專題
## 7/17(day97)
* 期末專題
## 7/18(day98)
* 期末專題
## 7/19(day99)
* 期末專題
## 7/22 ~ 7/26(day100 ~ day104)
* 期末專題
## 7/29 ~ 8/2(day105 ~ day109)
* 期末專題
## 8/5 ~ 8/8(day110 ~ day113)
* 期末專題&期末發表彩排
## 8/9(day114)
* 颱風假
## 8/13(day115)
* 期末發表&結業式
## 8/14(day116)
* 公司企業參訪(全曜、上詠、錢管家、金尉、超級物種、MDBS)
## 8/15(day117)
* CMoney筆試
###### tags: `java`