Try   HackMD

2023-05-07 Java 上課記錄

java

2023-05-07

標準輸出

public class App { public static void main(String[] args) { System.out.println("Hello, World!"); System.out.print("Hello, "); System.out.print("Aaron!"); System.out.printf("My name is %s", "Aaron"); } }

標準輸入

import java.io.BufferedReader; import java.io.InputStreamReader; public class App { /* 筆記,註解 */ public static void main(String[] args) throws Exception { // // 準備輸入用的變數 BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); System.out.print("請輸入第一個數字: "); String text1 = bf.readLine(); System.out.print("請輸入第二個數字: "); String text2 = bf.readLine(); int num1 = Integer.parseInt(text1); // 將num1轉換成數字 int num2 = Integer.parseInt(text2); // 將num1轉換成數字 System.out.println("總和為:" + (num1 + num2)); } }

偵測資料型態

import java.io.BufferedReader; import java.io.InputStreamReader; public class App { /* 筆記,註解 */ public static void main(String[] args) throws Exception { // 準備輸入用的變數 BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); System.out.print("請輸入第一個數字: "); String text1 = bf.readLine(); System.out.print("請輸入第二個數字: "); String text2 = bf.readLine(); int num1 = Integer.parseInt(text1); // 將num1轉換成數字 int num2 = Integer.parseInt(text2); // 將num1轉換成數字 System.out.println("總和為:" + (num1 + num2)); // 宣告type1變數 String type1 = ((Object)text2).getClass().getSimpleName(); System.out.println("text2的資料型態為: " + type1); type1 = ((Object)num1).getClass().getSimpleName(); System.out.println("num2的資料型態為: " + type1); } }

資料型態

import java.io.BufferedReader; import java.io.InputStreamReader; public class App { System.out.println("int最小值: " + Integer.MIN_VALUE); System.out.println("int最大值: " + Integer.MAX_VALUE); System.out.println("short最小值: " + Short.MIN_VALUE); System.out.println("short最大值: " + Short.MAX_VALUE); System.out.println("long最小值: " + Long.MIN_VALUE); System.out.println("long最大值: " + Long.MAX_VALUE); short test = (short)50000; System.out.println("Test:" + test); float a = (float)3.3; double b = 3.3; int c = (int)3.3; System.out.println("a=" + a); System.out.println("b=" + b); System.out.println("c=" + c); } }

比較運算

public static void main(String[] args) throws Exception { System.out.println("3 > 4的結果為: " + (3 > 4)); System.out.println("5 == 4的結果為: " + (5 == 4)); System.out.println("3 != 4的結果為: " + (3 != 4)); String type1 = ((Object)(3 != 4)).getClass().getSimpleName(); System.out.println(type1); }

產生隨機數

public class App { /* 筆記,註解 */ public static void main(String[] args) throws Exception { // 產生0~9之間的隨機整數 int a = (int)(Math.random() * 10); System.out.println(a); // 產生1~10之間的隨機整數 int b = (int)(Math.random() * 10) + 1; System.out.println(b); // 產生3~20之間的隨機整數 int c = (int)(Math.random() * 18) + 3; System.out.println(c); } }

if判斷

public class App { /* 筆記,註解 */ public static void main(String[] args) throws Exception { int a = 3; int b = 4; if(a < b) System.out.println("OK1"); else System.out.println("OK2"); } }

猜數字遊戲

開發一個猜數字遊戲:

  1. 電腦產生一個1~5之間的隨機整數
  2. 使用者輸入一個數字
  3. 顯示猜測結果,如果猜錯,並告知正確答案
import java.io.BufferedReader; import java.io.InputStreamReader; public class App { /* 筆記,註解 */ public static void main(String[] args) throws Exception { // 產生答案(1~5數字) int pc = (int)(Math.random() * 5) + 1; // 事先顯示答案,這行是測試用,正式產品要拿掉 System.out.println("答案: " + pc); // 使用者輸入 BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); System.out.println("猜數字遊戲"); System.out.println("------------------"); System.out.print("請輸入1~5之間的數字: "); // 接收使用者輸入 String userInput = bf.readLine(); // 將使用者輸入的字串轉為數字 int userInputNum = Integer.parseInt(userInput); if(pc == userInputNum) System.out.println("恭喜,猜對了"); else System.out.println("猜錯了,答案是: " + pc); } }

猜拳遊戲

開發一個猜拳遊戲:

  1. 電腦隨機生0~2之間的數字, 0=剪刀, 1=石頭, 2=布
  2. 使用者輸入0~2數字,代表剪刀,石頭,布
  3. 判斷結果更告知輸贏
import java.io.BufferedReader; import java.io.InputStreamReader; public class App { /* 筆記,註解 */ public static void main(String[] args) throws Exception { int pc = (int)(Math.random() * 3); // 顯示答案 if(pc == 0) System.out.println("電腦出: 剪刀"); if(pc == 1) System.out.println("電腦出: 石頭"); if(pc == 2) System.out.println("電腦出: 布"); BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); // 玩家出拳 System.out.print("請出拳(0=剪刀, 1=石頭, 2=布): "); int player = Integer.parseInt(bf.readLine()); // 電腦出剪刀,玩家出石頭 if(pc == 0 && player == 1) System.out.println("你贏了"); // 電腦出剪刀,玩家出布 if(pc == 0 && player == 2) System.out.println("你輸了"); // 電腦出石頭,玩家出剪刀 if(pc == 1 && player == 0) System.out.println("你輸了"); // 電腦出石頭,玩家出布 if(pc == 1 && player == 2) System.out.println("你贏了"); // 電腦出布,玩家出剪刀 if(pc == 2 && player == 0) System.out.println("你贏了"); // 電腦出布,玩家出石頭 if(pc == 2 && player == 1) System.out.println("你輸了"); if(pc == player) System.out.println("平手"); } }

提示:
此遊戲有更好的寫法,目前僅用已學習到的語法來開發此遊戲

2023-05-14

建立陣列

public class App { /* 筆記,註解 */ public static void main(String[] args) throws Exception { int[] a = new int[30]; // 建立一個可以存放30筆整數的陣列 a[0] = 30; System.out.println(a[0]); System.out.println(a[20]); System.out.println(a[23]); System.out.println(a[25]); System.out.println(a[27]); // 建立一個陣列,並直接把資料存放進去 int[] b = {3, 4, 5, 6, 7}; System.out.println(b[4]); } }

陣列練習

寫一程式,用來建立一筆客戶資料:

  1. 請使用者輸入: 姓名、英文名、生日、電話、地址等資料。
  2. 使用陣列存放。
  3. 建立後請將輸入的資料顯示到畫面上給使用者看。
import java.io.BufferedReader; import java.io.InputStreamReader; public class App { /* 筆記,註解 */ public static void main(String[] args) throws Exception { // 建立可以存放五筆資料的陣列 String[] userData = new String[5]; // 準備輸入物件 BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); // 接收使用者輸入 System.out.print("請輸入姓名: "); // 存下使用者輸入的姓名 userData[0] = bf.readLine(); System.out.print("請輸入英文名: "); userData[1] = bf.readLine(); System.out.print("請輸入生日: "); userData[2] = bf.readLine(); System.out.print("請輸入電話: "); userData[3] = bf.readLine(); System.out.print("請輸入住址: "); userData[4] = bf.readLine(); System.out.println("您輸入的姓名: " + userData[0] + ", 英文名: " + userData[1] + ", 生日: " + userData[2] + ", 電話: " + userData[3] + ", 地址: " + userData[4]); // 格式化字串 System.out.printf("您輸入的姓名: %s, 英文名: %s, 生日: %s, 電話: %s, 地址: %s", userData[0], userData[1], userData[2], userData[3], userData[4]); } }

二維陣列

import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.Arrays; import org.w3c.dom.UserDataHandler; public class App { /* 筆記,註解 */ public static void main(String[] args) throws Exception { String[][] userDatas = new String[3][]; userDatas[0] = new String[5]; // 建立內層的陣列 userDatas[0][0] = "姓名"; userDatas[0][1] = "英文名"; userDatas[0][2] = "生日"; userDatas[0][3] = "電話"; userDatas[0][4] = "地址"; userDatas[1] = new String[5]; // 建立內層的陣列 userDatas[1][0] = "ho"; userDatas[1][1] = "aaron"; userDatas[1][2] = "999"; userDatas[1][3] = "a888"; userDatas[1][4] = "xxxx"; System.out.println( Arrays.toString(userDatas[0]) ); System.out.println( Arrays.toString(userDatas[1]) ); System.out.println( Arrays.toString(userDatas[2]) ); } }

二維陣列也可以直接全部建立出來:

String[][] userDatas = new String[3][];

無窮迴圈與字串的equals()方法

  1. while(true)為一個無窮迴圈
  2. break為迴圈專用指令,用來中斷迴圈執行
  3. equals()為字串方法,用來比較字串,如果一樣的話會回得到true,反之為false
import java.io.BufferedReader; import java.io.InputStreamReader; public class App { /* 筆記,註解 */ public static void main(String[] args) throws Exception { BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); // 無窮迴圈 while(true) { System.out.print("請輸入: "); String userInput = bf.readLine(); // 比對userInput字串是不是quit System.out.println( userInput.equals("quit") ); // 比對使用者輸入的字串是否為quit if( userInput.equals("quit") ) break; // 結束迴圈 } } }

練習

寫一學生成績管理程式:

  1. 可儲存姓名、學號、國文、數學、英文成績
  2. 上限10筆
  3. 每輸入完一筆,詢問是否繼續,Y=繼續,N=結束
  4. 結束後將陣列資料顯示到畫面上
import java.io.BufferedReader; import java.io.InputStreamReader; import java.lang.reflect.Array; import java.nio.Buffer; import java.util.Arrays; public class App { public static void main(String[] args) throws Exception { BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); String[][] database = new String[10][5]; int index = 0; while(true) { System.out.print("請輸入姓名: "); database[index][0] = bf.readLine(); System.out.print("請輸入學號: "); database[index][1] = bf.readLine(); System.out.print("請輸入國文成績: "); database[index][2] = bf.readLine(); System.out.print("請輸入英文成績: "); database[index][3] = bf.readLine(); System.out.print("請輸入數學成績: "); database[index][4] = bf.readLine(); index++; if(index >= 10) break; System.out.println("請問要繼續嗎(Y=繼續, N=結束)?"); if(bf.readLine().equals("N")) break; } index = 0; while(true) { System.out.println(Arrays.toString(database[index])); index++; if(index >= 10) break; } System.out.println("程式結束"); } }

for迴圈求1~10總和

import java.io.BufferedReader; import java.io.InputStreamReader; import java.lang.reflect.Array; import java.nio.Buffer; import java.util.Arrays; public class App { public static void main(String[] args) throws Exception { int sum = 0; for(int i = 1 ; i <= 10 ; i++) { sum = sum + i; } System.out.println(sum); } }

for迴圈求階層

寫一程式,使用者輸入一個整數,算出階乘後顯示到畫面上

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Array;
import java.nio.Buffer;
import java.util.Arrays;

public class App {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        System.out.print("請輸入數字: ");
        String userInput = br.readLine();
        int userInputInt = Integer.parseInt(userInput);

        int sum = 1;

        for(int i = 1 ; i <= userInputInt ; i++) {
            sum = sum * i;
        }

        System.out.printf("%d的階乘為: %d", userInputInt, sum);
    }   
}

奇偶數判斷

寫一程式,使用者輸入一個整數,判斷該數字為奇數或偶數後顯示到畫面上。

import java.io.BufferedReader; import java.io.InputStreamReader; import java.lang.reflect.Array; import java.nio.Buffer; import java.util.Arrays; public class App { public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.print("請輸入數字: "); String userInput = br.readLine(); int userInputInt = Integer.parseInt(userInput); if(userInputInt % 2 == 1) System.out.println("奇數"); else System.out.println("偶數"); } }

桃園UBike剩餘量查詢

下載套件

OpenCSV: https://sourceforge.net/projects/opencsv/

Apache common-lang3: https://mvnrepository.com/artifact/org.apache.commons/commons-lang3/3.12.0

資料欄位說明

索引 欄位名稱 說明
0 sareaen 行政區英文名
1 sarea 行政區中文名
2 lng 經度
3 sna 中文站名
4 snaen 英文站名
5 bemp 空位數量
6 ar 中文地址
7 act 全站禁用狀態(0:禁用、1:啟用)
8 sno 站編號
9 aren 英文地址
10 tot 場站總停車格
11 _id 資料編號
12 sbi 場站目前車輛數量
13 mday 微笑單車各場站來源資料更新時間
14 lat 緯度
import java.io.BufferedReader; import java.io.InputStreamReader; import java.lang.reflect.Array; import java.net.HttpURLConnection; import java.net.URL; import java.nio.Buffer; import java.util.Arrays; import com.opencsv.CSVReader; public class App { public static void main(String[] args) throws Exception { // Ubike OpenData 網址 final String openDataUrl = "https://data.tycg.gov.tw/api/v1/rest/datastore/a1b4714b-3b75-4ff8-a8f2-cc377e4eaa0f?format=csv&limit=1000"; // 建立URL物件 URL ubikeUrl = new URL(openDataUrl); // 開始連線,並取得連線用的物件 HttpURLConnection connection = (HttpURLConnection)ubikeUrl.openConnection(); // 200代表連線成功 if(connection.getResponseCode() == 200) { System.out.println("連線成功"); // 建立讀取網頁/CSV資料的物件 InputStreamReader isr = new InputStreamReader(connection.getInputStream(), "UTF-8"); // 建立CSVReader物件來解析CSV格式資料 CSVReader csvReader = new CSVReader(isr); String[] row = csvReader.readNext(); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.print("請輸入站名: "); String userInput = br.readLine(); while( (row = csvReader.readNext()) != null) { // System.out.println(Arrays.toString(row)); if(row[3].indexOf(userInput) != -1) { System.out.printf("站名: %s, 地址: %s\n", row[3], row[6]); System.out.printf(" - 可借: %s\n", row[12]); System.out.printf(" - 可還: %s\n", row[5]); System.out.printf(" - 總數: %s\n\n", row[10]); } } // 用完要呼叫close關閉連線 csvReader.close(); } else { System.out.println("連線失敗"); } } }

2023-05-21

判斷式的兩種寫法

寫一算命程式,使用者執行後,從10之籤裡面抽出一支,如果抽到:
1 = 今天會撿到錢,今天會中樂透
2 = 今天考試100分
3 = 今天會有豔遇
4~10 = 今天不會有特別事發生

public class App { public static void main(String[] args) throws Exception { // 從10之籤裡面抽一支籤(隨機數10個) int lucky = (int)(Math.random() * 10) + 1; System.out.println(lucky); if(lucky == 1) System.out.println("今天會撿到錢"); // 縮排 if(lucky == 2) System.out.println("今天考試100分"); if(lucky == 3) System.out.println("今天有豔遇"); if(lucky >= 4 && lucky <= 10) System.out.println("今天沒有特別事情發生"); } }

下面的判斷式寫法,寫率會比較好:

int lucky = (int)(Math.random() * 10) + 1; System.out.println(lucky); if(lucky == 1) { System.out.println("今天會撿到錢"); System.out.println("今天會中樂透"); } else if(lucky == 2) System.out.println("今天考試100分"); else if(lucky == 3) System.out.println("今天有豔遇"); else System.out.println("今天沒有特別事情發生"); } }

switch判斷式

寫一算命程式,使用者執行後,從10之籤裡面抽出一支,如果抽到:
1 = 今天會撿到錢,今天會中樂透
2 = 今天考試100分
3 = 今天會有豔遇
4、5 = 今天心情好
6、7、8 = 今天加薪
9~10 = 今天不會有特別事發生

public class App { public static void main(String[] args) throws Exception { // 從10之籤裡面抽一支籤(隨機數10個) int lucky = (int)(Math.random() * 10) + 1; System.out.println(lucky); switch(lucky) { case 1: System.out.println("今天會撿到錢"); System.out.println("今天會種樂透"); break; case 2: System.out.println("今天會考100分"); break; case 3: System.out.println("今天有豔遇"); break; case 4: case 5: System.out.println("今天心情好好"); break; default: System.out.println("今天沒有特別事情發生"); break; } } }

迴圈複習

寫一程式:

  1. 使用者可以輸入任意個數字
  2. 將使用者輸入的數字顯示到畫面上,格式如下:
    ​​​輸入了: 3
    ​​​輸入了: 13
    ​​​輸入了: 245
    ​​​輸入了: 87
    
  3. 將奇數和偶數分別加總後顯示到畫面上
  4. 將所有數字頻軍後顯示到畫面上
import java.io.BufferedReader; import java.io.InputStreamReader; public class App { public static void main(String[] args) throws Exception { // 準備輸入用物件 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 存放使用者輸入的數字(最多1000個) int[] userInputs = new int[1000]; // 紀錄使用者輸入了幾個數字 int count = 0; // 1. 使用者可以輸入任意個數字 while(true) { System.out.print("請輸入一個數字: "); // 接受使用者輸入(型態為字串) String user = br.readLine(); // 將字串轉成數字 int userInt = Integer.parseInt(user); // 將轉換好的數字存到陣列,以count為索引的位置去 userInputs[count] = userInt; // 詢問使用者是否要繼續輸入 System.out.print("請問使否要繼續輸入(Y=繼續,N=結束)? "); // 使用者輸入Y或N String ask = br.readLine(); // 如果使用者輸入N,結束迴圈 if(ask.equals("N")) break; // 將索引加1 count++; if(count >= 1000) { System.out.println("儲存空間已滿"); // 離開迴圈 break; } } } }

另一種寫法

import java.io.BufferedReader; import java.io.InputStreamReader; public class App { public static void main(String[] args) throws Exception { // 準備輸入用物件 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 存放使用者輸入的數字(最多1000個) int[] userInputs = new int[1000]; // 紀錄使用者輸入了幾個數字 int count = 0; // 1. 使用者可以輸入任意個數字 while(true) { System.out.print("請輸入一個數字,輸入N來結束輸入: "); // 接受使用者輸入(型態為字串) String user = br.readLine(); // 如果使用者輸入N,結束迴圈 if(user.equals("N")) break; // 將字串轉成數字 int userInt = Integer.parseInt(user); // 將轉換好的數字存到陣列,以count為索引的位置去 userInputs[count] = userInt; // 將索引加1 count++; if(count >= 1000) { System.out.println("儲存空間已滿"); // 離開迴圈 break; } } System.out.printf("總共輸入了%d個數字.\n", count); // 2. 將使用這輸入的數字顯示出來 for(int i = 0 ; i < count ; i++) { System.out.printf("輸入了: %d\n", userInputs[i]); } // 3. 將奇數跟偶數分別加總後顯示到畫面上 int odd = 0; // 存放奇數加總用 int even = 0; // 存放偶數加總用 for(int i = 0 ; i < count ; i++) { // 偶數加總 if(userInputs[i] % 2 == 0) even += userInputs[i]; // 奇數加總 else odd += userInputs[i]; } System.out.printf("奇數總和為: %d\n偶數總和為: %d\n", odd, even); // 4. 將所有的數字平均後顯示出來 int total = 0; // 存放加總用 for(int i = 0 ; i < count ; i++) { // 將陣列所有數字加總到total變數內 total += userInputs[i]; } System.out.printf("平均: %.1f", (float)total / count); // %d=整數, %f=小數, %.1f表示顯示到小數以下第一位 } }

do-while

以下兩個while迴圈結果一樣,但是do-while迴圈可以有效減少同富的程式碼。

BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // ============================================================== System.out.print("請輸入(不輸入,ENTER來結束):"); String userInput = br.readLine(); while(userInput.length() > 0) { System.out.println("你輸入了: " + userInput); System.out.print("請輸入(不輸入,ENTER來結束):"); userInput = br.readLine(); } System.out.println("結束"); // =============================================================== String userInput2 = ""; do { System.out.print("請輸入(不輸入,ENTER來結束):"); userInput2 = br.readLine(); if(userInput2.length() > 0) System.out.println("你輸入了: " + userInput2); }while(userInput2.length() > 0); System.out.println("結束"); } }

提示:
while和do-while唯一差別為: do-while迴圈不館條件有無成立,至少都會被執行一次。

上面範例的while的另一種寫法

BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // ============================================================== System.out.print("請輸入(不輸入,ENTER來結束):"); String userInput = ""; while((userInput = br.readLine()).length() > 0) { System.out.println("你輸入了: " + userInput); System.out.print("請輸入(不輸入,ENTER來結束):"); } System.out.println("結束");

說明:
把使用者輸入直接和條件式結合在一起的寫法,請記得指派運算子的左右兩邊一定要加上小括號,讓指派這個動作最優先完成。

ArrayList

public class App { public static void main(String[] args) throws Exception { ArrayList<String> a = new ArrayList<>(); a.add("abc"); a.add("def"); a.add("000"); a.add("def"); a.add("def"); a.add(0, "111"); a.remove(3); a.remove("def"); a.remove("def"); a.remove("def"); a.remove("def"); a.remove("def"); a.remove("def"); System.out.println(a); System.out.println("陣列有幾筆資料: " + a.size()); } }

AB遊戲開發

開發步驟
  1. 0-9隨機出四個數字且不重複當答案(使用ArrayList)
  2. 接收使用者輸入並轉換成ArrayList
  3. 加上迴圈讓使用者可以不斷猜數字
  4. 記錄猜幾次
  5. 提示幾A幾B
  6. 加入例外判斷
import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import javax.print.attribute.HashAttributeSet; public class App { public static void main(String[] args) throws Exception { ArrayList<String> answer = new ArrayList<>(); answer.add("0"); answer.add("1"); answer.add("2"); answer.add("3"); answer.add("4"); answer.add("5"); answer.add("6"); answer.add("7"); answer.add("8"); answer.add("9"); Collections.shuffle(answer); answer.remove(4); answer.remove(4); answer.remove(4); answer.remove(4); answer.remove(4); answer.remove(4); System.out.println("答案: " + answer); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 預備用來存放使用者答案的動態陣列 ArrayList<String> user = new ArrayList<>(); // 紀錄猜了幾次 int count = 0; do { System.out.print("請輸入四個不重覆數字: "); // 使用者輸入答案 String userInput = br.readLine(); // 猜測次數加一 count++; // 判斷使用者是不是輸入四個字 if(userInput.length() != 4) { System.out.println("輸入的數字不是四個,請重新輸入。"); // 停止執行迴圈剩下的程式碼,並回到開頭重新下一輪 continue; } try { Integer.parseInt(userInput); } catch(NumberFormatException e) { System.out.println("只能輸入數字。"); // 停止執行迴圈剩下的程式碼,並回到開頭重新下一輪 continue; } // 將使用者的答案切開陣列 String[] userInputArray = userInput.split(""); // 清除上次猜的答案 user.clear(); // 將陣列轉換成List並加入到user這個ArrayList內 user.addAll(Arrays.asList(userInputArray)); // 判斷輸入的數字有沒有重複 HashSet<String> test = new HashSet<>(); test.addAll(user); System.out.println("使用者輸入: " + user); System.out.println("使用者輸入HashSet: " + test); if(test.size() != 4) { System.out.println("數字不可重複。"); continue; } // 紀錄幾個A int howManyA = 0; if(answer.get(0).equals(user.get(0))) howManyA++; if(answer.get(1).equals(user.get(1))) howManyA++; if(answer.get(2).equals(user.get(2))) howManyA++; if(answer.get(3).equals(user.get(3))) howManyA++; // 紀錄幾個B int howManyB = 0; if(answer.contains(user.get(0)) && answer.get(0).equals(user.get(0)) == false) howManyB++; if(answer.contains(user.get(1)) && answer.get(1).equals(user.get(1)) == false) howManyB++; if(answer.contains(user.get(2)) && answer.get(2).equals(user.get(2)) == false) howManyB++; if(answer.contains(user.get(3)) && answer.get(3).equals(user.get(3)) == false) howManyB++; System.out.printf("%dA%dB\n", howManyA, howManyB); }while(answer.equals(user) == false); // 答案不同就繼續猜 System.out.printf("猜對了, 遊戲結束, 總共猜了%d次\n", count); } }

補充:

  • continue用在回圈內,當遇到continue的時候,忽略剩下的程式碼,並回到迴圈開頭重新執行。
  • HashSet的特性就是,存進去的資料絕對不會重複,如果重複存入相同資料,會被自動刪掉。

2023-05-28

畫出三角形

for(int i = 4 ; i >= 0 ; i--) { for(int j = i ; j < 5 ; j++) { System.out.println("*") } System.out.println(); // 只是為了換行用 }

輸出:

*
**
***
****
*****

三元運算子

Java內有唯一的一個三元運算子?:,專門用來簡化if-else判斷式,例如:

if(score < 60) System.out.println("不及格"); else System.out.println("及格");

可以用三元運算子改寫成:

System.out.println(score < 60 ? "不及格":"及格");

++和複習

int i = 0; int ok = i == 1 ? i++ : i--; System.out.println(ok);

輸出為:

0

說明:
因為i和i的運算元在後面,所以當i被指派給ok之後才會進行,因此這裡的ok會是0。

Java命名規則(適用於類別、方法、欄位、變數等等的命名)

  1. 只能使用英文、數字、底線來命名
  2. 名稱的第一個字不可為數字
  3. 不可使用Java的保留字(如: switch、int、if都不能用來當名字)

補充:

  1. 方法、欄位、變數命名習慣上第一個字會使用英文小寫
  2. 類別命名習慣上第一個字會使用英文大寫
  3. 常數命名習慣上名字會全部用大寫

方法

public class App { // 程式進入點 public static void main(String[] args) throws Exception { myFunc(); // 呼叫方法 } // Java習慣上,方法的第一個字母為小寫,第二個單字開始,第一個字母為大寫 // 方法只有被呼叫才會執行 public static void myFunc() { System.out.println("我的方法(method)"); myFunc2(); } public static void myFunc2() { System.out.println("我的第三個方法"); } }

建立非靜態方法

// public class App { // 程式進入點 public static void main(String[] args) throws Exception { myFunc(); // 呼叫方法 } // Java習慣上,方法的第一個字母為小寫,第二個單字開始,第一個字母為大寫 // 方法只有被呼叫才會執行 public static void myFunc() { System.out.println("我的方法(method)"); myFunc2(); App a = new App(); // 以App類別來建立App物件 a.myFunc3(); // 呼叫方法 } public static void myFunc2() { System.out.println("我的第三個方法"); } // 非靜態方法 public void myFunc3() { System.out.println("我的非靜態方法"); } }

建立類別

建立一個Car類別,在類別內:

  1. 建立color欄位,型態為String
  2. 建立run方法,型態為void
  3. 建立setColor,型態為void
  4. 建立gas欄位,型態為int
  5. 建立setGas方法,型態為void,有一參數gas,型態為int
  6. 建立show方法,型態為void
Car.java
public class Car { private String color; // color欄位(Field) private int gas; // 私有欄位 // 建構式 // 1. 沒有型態(回傳值) // 2. 名字跟類別一樣 // 3. 通常為public public Car() { // 初始化 System.out.println("我是建構式"); } // 建構式可以多個,但是參數不能一樣 public Car(int gas) { System.out.println("有參數的建構式"); this.gas = gas; } public Car(String color) { System.out.println("有字串參數的建構式"); this.color = color; } public Car(int gas, String color) { System.out.println("有參數得建構式二號"); this.gas = gas; this.color = color; } public void run() { System.out.println("開車"); } public void setColor(String color) { System.out.println("將車子顏色變更為" + color); this.color = color; // 把color參數指派給color欄位 } public void setGas(int gas) { System.out.println("將汽油加到" + gas + "公升"); this.gas = gas; } // setGas的多載版本 public void setGas() { System.out.println("將汽油清空"); this.gas = 0; } public void setGas(int gas, int gas2) { this.gas = gas + gas2; } public void show() { System.out.printf("車子顏色為: %s, 汽油剩餘: %d公升\n", this.color, gas); } public static void getCategory() { System.out.println("我是車子"); } // 1. 方法必須定義要回傳的資料型態 // 2. 必須使用return指令來將資料回傳到呼叫方 // 3. 呼叫方需在同一行程式碼處理回傳的資料(存到變數或直接顯示) public int getGas() { return gas; } // 取得Car物件的顏色 public String getColor() { return color; } }

說明:

  1. 變數只能在該方法內被看到(又稱為生命週期為該變數內)
  2. 欄位整個類別內的方法都可以看到(又稱為生命週期為該物件內)
  3. 靜態欄位生命週期為整個程式執行時
App.java
public class App { // 程式進入點 public static void main(String[] args) throws Exception { Car.getCategory(); Car car = new Car(); // 使用Car類別建立Car物件 // 這裡會呼叫建構式 car.setGas(20); car.setColor("白色"); Car car1 = new Car(); // 這裡會呼叫建構式 car1.setGas(15); car1.setColor("紅色"); car.show(); car1.show(); car.run(); car1.run(); car.getCategory(); car1.getCategory(); Car car2 = new Car(34); car2.show(); Car car3 = new Car(55, "彩色"); car3.setColor("黑色"); car3.show(); Car car4 = new Car("彩色"); car4.show(); } }

物件的指派為參考

public class App { // 程式進入點 public static void main(String[] args) throws Exception { Car car = new Car(30, "彩色"); Car car2 = car; // 將car的參考存到car2內 car2.setColor("黑色"); car.show(); int a = 9; int b = a; // 將a的內容複製給b b += 1; System.out.println(a); } }

方法回傳值

public class App { // 程式進入點 public static void main(String[] args) throws Exception { Car car = new Car(30, "彩色"); int a = car.getGas(); // 這個方法會回傳一個int, 因此必須存下來才不會消失 System.out.println("得到了汽油:" + a + "公升"); } }

私有欄位無法直接存取

public class App {
    // 程式進入點
    public static void main(String[] args) throws Exception {
        Car car = new Car(30, "彩色");
        
        int a = car.getGas();  // 這個方法會回傳一個int, 因此必須存下來才不會消失
        System.out.println("得到了汽油:" + a + "公升");

        String c = car.getColor();
        System.out.println("得到了車子顏色為: " + c);

        // car.gas= 999;

        // System.out.println(car.color);  因為欄位被設定成private所以無法直接存取
        // System.out.println(car.gas);
    }
}

方法多載(overload)

public class App { // 程式進入點 public static void main(String[] args) throws Exception { Car car = new Car(); car.setGas(12, 34); car.show(); } }

小遊戲

App.java
public class App { // 程式進入點 public static void main(String[] args) throws Exception { // 建立遊戲世界 World world = new World(); // 開始遊戲 world.play(); } }
Monster
import java.util.TimerTask; // TimerTask定時器 public class Monster extends TimerTask { private String name = "無名怪"; public Monster(String name) { this.name = name; } public void run() { int action = (int)(Math.random() * 5); switch(action) { case 0: System.out.println(name + " 向左走了一步"); break; case 1: System.out.println(name + " 向右走了一步"); break; case 2: System.out.println(name + " 向前走了一步"); break; case 3: System.out.println(name + " 向後走了一步"); break; case 4: System.out.println(name + " 攻擊了玩家"); break; } } }
Dog.java
import java.util.TimerTask; // TimerTask定時器 public class Dog extends TimerTask { private String name = "無名狗"; public Dog(String name) { this.name = name; } public void run() { int action = (int)(Math.random() * 3); switch(action) { case 0: System.out.println(name + " 大聲喊叫"); break; case 1: System.out.println(name + " 咆嘯"); break; case 2: System.out.println(name + " 咬了玩家一口"); break; } } }
World.java
import java.util.Timer; public class World { private Timer timer; public World() { // 建立計時器 timer = new Timer(); } public void addMonstor(Monster m) { // 1000=加入timer後多久開始行動, 2000=每隔多久行動一次 timer.schedule(m, 1000, 3000); } public void addDog(Dog d) { timer.schedule(d, 0, 1500); } // 啟動遊戲 public void play() throws InterruptedException { // 加入史萊姆 for(int i = 0 ; i < 20 ; i++) { String name = "史萊姆" + i + "號"; addMonstor(new Monster(name)); System.out.println(name + " 在地圖上出現了..."); // 延遲一點時間 int delay = (int)(Math.random() * 5) + 1; Thread.sleep(delay * 1000); // 單位: 毫秒 } // 加入狗 for(int i = 0 ; i < 10 ; i++) { String name = "狗狗" + i + "號"; addDog(new Dog(name)); System.out.println(name + " 在地圖上出生了..."); // 延遲一點時間 int delay = (int)(Math.random() * 5) + 5; Thread.sleep(delay * 1000); // 單位: 毫秒 } } }

2023-06-04

繼承

跑車類別: SportCar.java
package CarStore; public class SportCar extends Car { // 建構式 public SportCar(String color, int gas) { super(color, gas); this.type = "跑車"; } public void trubo() { System.out.println("進入競速模式"); } public boolean equals(SportCar s) { // if(color.equals(s.color)) { // return true; // } else { // return false; // } return color.equals(s.color); } }
卡車類別: Truck.java
package CarStore; public class Truck extends Car { public String type = "卡車"; public Truck(String color, int gas) { super(color, gas); // 呼叫父類別建構式 } public void release() { System.out.println("卸貨"); } public void show() { System.out.printf("我是一輛%s, 顏色: %s, 汽油: %d公升\n", type, color, gas); } }
汽車類別: Car.java
package CarStore; public class Car { public String type = "車子"; public String color = "白色"; public int gas = 0; public Car(String color, int gas) { this.color = color; this.gas = gas; } public void start() { System.out.printf("%s啟動\n", type); } public void run() { System.out.println("開車"); } public void show() { System.out.printf("我是一輛%s, 顏色: %s, 汽油: %d公升\n", type, color, gas); } public String toString() { return "我是一輛" + type + ", 顏色: " + color + ", 汽油: " + gas + "公升"; } }
App.java
import Ford.Truck; public class App { // 程式進入點 public static void main(String[] args) throws Exception { Nissan.SportCar sportCar = new Nissan.SportCar("紅色", 20); sportCar.start(); sportCar.run(); sportCar.show(); sportCar.trubo(); Truck truck = new Truck("藍色", 50); truck.start(); truck.run(); truck.show(); truck.release(); CarStore.Truck t2 = new CarStore.Truck("..", 0); System.out.println( sportCar.toString() ); System.out.println( truck.toString() ); Ford.SportCar sportCar2 = new Ford.SportCar("紅色", 20); if(sportCar.equals(sportCar2) == true) { System.out.println("兩輛車一樣"); } else { System.out.println("兩輛車不一樣"); } } }
目錄結構

Object類別

所有的Java類別就會被繼承自Object類別

Image from: https://www.geeksforgeeks.org/object-class-in-java/

JAR

如果要分享開發好的package,建議先打包成jar檔,以jar檔的方式來分享。

修飾子

  • public
  • protected
  • private
  • (no modifier)
public protected private (無修飾子)
同套件不同類別 V V X V
同套件子類別 V V X V
不同套件不同類別 V X X X
不同套件子類別 V V X X

Singlton

World.java
public class World { private World() { System.out.println("建立遊戲世界"); } public void start() { System.out.println("啟動遊戲"); } private static World world = null; public static World getInstance() { if(world == null) { world = new World(); } return world; } }
App.java
public class App { // 程式進入點 public static void main(String[] args) throws Exception { World world = World.getInstance(); world.start(); World world2 = World.getInstance(); world2.start(); } }

說明:
此範例為設計模式的Singleton(單體)模式

static 複習

  • static不需要建立物件就可以直接存取/呼叫

  • static整個程式內只會有一份實體
     > 也就是說同一個類別的同一個靜態欄位不管建立幾個物件,其資料都是共通的

  • 生命週期為整個程式執行的期間

  • static方法不可以直接使用非static的欄位和方法

public class App { // 程式進入點 public static void main(String[] args) throws Exception { Test.b = 77; System.out.println(Test.b); Test test = new Test(); System.out.println(test.a); System.out.println(test.b); Test test2 = new Test(); System.out.println(test2.b); test2.b = 111; System.out.println(test.b); System.out.println(Test.b); Test.showB(); } } class Test { public int a = 99; public static int b = 88; public static void showB() { System.out.println(b); System.out.println(a); // 不行 Test test = new Test(); System.out.println(test.a); // 行 } public void showA() { System.out.println(b); } }

多型

父類別型態定義的變數可以存放子類別建立出來的物件。

import java.util.ArrayList; import SportCar.SportCar; import SportCar.Truck; import SportCar.Bus; import SportCar.Car; public class App { // 程式進入點 public static void main(String[] args) throws Exception { ArrayList<Car> cars = new ArrayList<>(); cars.add(new SportCar("黑色", 20)); cars.add(new SportCar("白色", 20)); cars.add(new SportCar("紅色", 20)); cars.add(new SportCar("黃色", 20)); cars.add(new Truck("黑色", 20)); cars.add(new Truck("藍色", 20)); cars.add(new Truck("棕色", 20)); cars.add(new Bus()); cars.add(new Bus()); for(Car s : cars) { s.show(); } } }

小遊戲

寫一遊戲:

  1. 隨機產生0~100之間整數(例如: 77)
  2. 使用者猜一數字(例如: 40)
  3. 程式提示範圍為: 40~100
  4. 再猜90
  5. 提示範圍: 40~90
  6. 一直循環,直到猜對數字後告知猜了幾次
RandomGame.java
import java.io.BufferedReader; import java.io.InputStreamReader; public class RandomGame { private int answer = 0; private BufferedReader br = null; public RandomGame(int min, int max) { answer = (int)(Math.random() * (max - min)) + min; br = new BufferedReader(new InputStreamReader(System.in)); System.out.println("答案: " + answer); } protected int getAnswer() { return answer; } protected int getInputInt(String prompt) throws Exception { System.out.print(prompt); return Integer.parseInt(this.br.readLine()); } }
UltimatePassword.java
public class UltimatePassowrd extends RandomGame { public final static int MIN_ANSWER = 0; public final static int MAX_ANSWER = 100; private int min = MIN_ANSWER; private int max = MAX_ANSWER; private int count = 0; protected UltimatePassowrd() { super(MIN_ANSWER, MAX_ANSWER); } public void play() throws Exception { final int answer = this.getAnswer(); while(true) { int user = this.getInputInt("請輸入0~100之間的數字: "); count++; if(user > answer) { max = user; } else if(user < answer) { min = user; } else { System.out.println("猜對了,總共猜了" + count + "次."); break; } System.out.printf("猜錯,範圍為: %d ~ %d 之間\n", min, max); } } }
App.java
public class App { // 程式進入點 public static void main(String[] args) throws Exception { new UltimatePassowrd().play(); } }

2023-06-11

多型

import java.util.ArrayList; class Animal { public void walk() { System.out.println("走路"); } public void type() { System.out.println("動物"); } } class Cat extends Animal { public void walk() { System.out.print("四隻腳"); super.walk(); // 呼叫父類別walk } public void jump() { System.out.println("跳躍"); } public void type() { System.out.println("貓"); } } class Bird extends Animal { public void walk() { // override System.out.print("兩隻腳"); super.walk(); // 呼叫父類別walk } public void fly() { System.out.println("飛翔"); } public void type() { System.out.println("鳥"); } } public class App { // 程式進入點 public static void main(String[] args) throws Exception { Cat cat = new Cat(); cat.walk(); Bird bird = new Bird(); bird.walk(); Animal a1 = new Cat(); // animal變數存放的是Cat物件 a1.walk(); // a1.fly(); // Cat沒有fly方法,有也會被裁切掉 Animal a0 = new Animal(); a0.walk(); Animal a2 = new Bird(); a2.walk(); // a2.fly(); // 因為透過Animal來存放Bird物件,而Animal類別只認識walk方法,所以fly方法被裁切掉了,無法呼叫 ((Bird)a2).fly(); // 強制轉型回Bird型態,所以可以呼叫fly方法了 ArrayList<Animal> arrayList = new ArrayList<>(); arrayList.add(a0); arrayList.add(a1); arrayList.add(a2); arrayList.add(bird); for(Animal a : arrayList) { a.type(); a.walk(); } } }

抽象類別&抽象方法

  1. 當一個方法只是為了當介面,可以不時做實體,直接將該方法加上abstract變成抽象方法
  2. 當一個類別包含抽象方法,該類別也必需加上abstract變成抽象類別
  3. 抽象類別無法透過new來建立實體物件
// 當類別裡面出現抽象方法,該類別必須也變成抽象類別 abstract class Animal { public void walk() { System.out.println("走路"); } // type方法沒有用處,不會呼叫,但是需要給子類別當作介面 public abstract void type(); // 抽象方法 } class Cat extends Animal { public void walk() { System.out.print("四隻腳"); super.walk(); // 呼叫父類別walk } public void jump() { System.out.println("跳躍"); } public void type() { System.out.println("貓"); } } class Bird extends Animal { public void walk() { // override System.out.print("兩隻腳"); super.walk(); // 呼叫父類別walk } public void fly() { System.out.println("飛翔"); } public void type() { System.out.println("鳥"); } } public class App { // 程式進入點 public static void main(String[] args) throws Exception { // 抽象類別無法被實體化,也就是無法透過new建立抽象類別的物件 // Animal a0 = new Animal(); // a0.type(); Animal a1 = new Cat(); a1.type(); Animal a2 = new Bird(); a2.type(); } }

積木app

方法版本
public class App { public static void main(String[] args) throws Exception { App app = new App(); // app.RTriangle(); app.RTriangle(); app.Rectangle(); // 空白行 System.out.println(); // app.Triangle(); app.Rectangle(); app.RTriangle(); // 空白行 System.out.println(); // app.Rectangle(); app.RTriangle(); app.Triangle(); } public void Triangle() { System.out.println(" * "); System.out.println(" *** "); } public void RTriangle() { System.out.println(" *** "); System.out.println(" * "); } public void Rectangle() { System.out.println("*****"); System.out.println("*****"); } }
類別
class Triangle { public void draw() { System.out.println(" * "); System.out.println(" *** "); } } class RTriangle { public void draw() { System.out.println(" *** "); System.out.println(" * "); } } class Rectangle { public void draw() { System.out.println("*****"); System.out.println("*****"); } } public class App { public static void main(String[] args) throws Exception { // Triangle triangle = new Triangle(); RTriangle rTriangle = new RTriangle(); Rectangle rectangle = new Rectangle(); triangle.draw(); rTriangle.draw(); rectangle.draw(); // 空白行 System.out.println(); // triangle.draw(); rectangle.draw(); rectangle.draw(); // 空白行 System.out.println(); // rectangle.draw(); rTriangle.draw(); triangle.draw(); } }
多型化
abstract class Shape { public abstract void draw(); } class Triangle extends Shape { public void draw() { System.out.println(" * "); System.out.println(" *** "); } } class RTriangle extends Shape { public void draw() { System.out.println(" *** "); System.out.println(" * "); } } class Rectangle extends Shape { public void draw() { System.out.println("*****"); System.out.println("*****"); } } public class App { public static void main(String[] args) throws Exception { // Shape triangle = new Triangle(); Shape rTriangle = new RTriangle(); Shape rectangle = new Rectangle(); triangle.draw(); rTriangle.draw(); rectangle.draw(); // 空白行 System.out.println(); // triangle.draw(); rectangle.draw(); rectangle.draw(); // 空白行 System.out.println(); // rectangle.draw(); rTriangle.draw(); triangle.draw(); } }
多型繪圖
import java.util.ArrayList; abstract class Shape { public abstract void draw(); } class Triangle extends Shape { public void draw() { System.out.println(" * "); System.out.println(" *** "); } } class RTriangle extends Shape { public void draw() { System.out.println(" *** "); System.out.println(" * "); } } class Rectangle extends Shape { public void draw() { System.out.println("*****"); System.out.println("*****"); } } public class App { public static void main(String[] args) throws Exception { // Shape triangle = new Triangle(); Shape rTriangle = new RTriangle(); Shape rectangle = new Rectangle(); // 圖形1 ArrayList<Shape> shape1 = new ArrayList<>(); shape1.add(triangle); shape1.add(rTriangle); shape1.add(rectangle); // 圖形2 ArrayList<Shape> shape2 = new ArrayList<>(); shape2.add(triangle); shape2.add(rectangle); shape2.add(rectangle); // Shape 1 for(Shape s : shape1) s.draw(); // 空白行 System.out.println(); // Shape 2 for(Shape s : shape2) s.draw(); // 空白行 System.out.println(); // Shape 1 for(Shape s : shape1) s.draw(); // 空白行 System.out.println(); // Shape 2 for(Shape s : shape2) s.draw(); // 空白行 System.out.println(); // Shape 1 for(Shape s : shape1) s.draw(); // 空白行 System.out.println(); // Shape 2 for(Shape s : shape2) s.draw(); } }
改成介面
import java.util.ArrayList; // 介面一定都是抽象的 interface IShape { public void draw(); } // 透過implements來實作介面 class Triangle implements IShape { public void draw() { System.out.println(" * "); System.out.println(" *** "); } } class RTriangle implements IShape { public void draw() { System.out.println(" *** "); System.out.println(" * "); } } class Rectangle implements IShape { public void draw() { System.out.println("*****"); System.out.println("*****"); } } public class App { public static void main(String[] args) throws Exception { // IShape triangle = new Triangle(); IShape rTriangle = new RTriangle(); IShape rectangle = new Rectangle(); // 圖形1 ArrayList<IShape> shape1 = new ArrayList<>(); shape1.add(triangle); shape1.add(rTriangle); shape1.add(rectangle); // 圖形2 ArrayList<IShape> shape2 = new ArrayList<>(); shape2.add(triangle); shape2.add(rectangle); shape2.add(rectangle); // Shape 1 for(IShape s : shape1) s.draw(); // 空白行 System.out.println(); // Shape 2 for(IShape s : shape2) s.draw(); // 空白行 System.out.println(); // Shape 1 for(IShape s : shape1) s.draw(); // 空白行 System.out.println(); // Shape 2 for(IShape s : shape2) s.draw(); // 空白行 System.out.println(); // Shape 1 for(IShape s : shape1) s.draw(); // 空白行 System.out.println(); // Shape 2 for(IShape s : shape2) s.draw(); } }
實作多個介面
import java.util.ArrayList; // 介面一定都是抽象的 interface IShape { int a = 5; // 這是個final,無法被修改 public void draw(); } interface IWork { public void run(); } // 透過implements來實作介面 class Triangle implements IShape, IWork { public void draw() { System.out.println(" * "); System.out.println(" *** "); } @Override public void run() { System.out.println("Triangle實作run方法"); } } class RTriangle implements IShape, IWork { public void draw() { System.out.println(" *** "); System.out.println(" * "); } @Override public void run() { System.out.println("RTriangle"); } } class Rectangle implements IShape, IWork { public void draw() { System.out.println("*****"); System.out.println("*****"); } @Override public void run() { System.out.println("Rectangle"); } } public class App { public static void main(String[] args) throws Exception { System.out.println(IShape.a); // IShape.a = 8; // 無法被修改 // IShape triangle = new Triangle(); IShape rTriangle = new RTriangle(); IShape rectangle = new Rectangle(); IWork w1 = (IWork)triangle; w1.run(); // 圖形1 ArrayList<IShape> shape1 = new ArrayList<>(); shape1.add(triangle); shape1.add(rTriangle); shape1.add(rectangle); // 圖形2 ArrayList<IShape> shape2 = new ArrayList<>(); shape2.add(triangle); shape2.add(rectangle); shape2.add(rectangle); // Shape 1 for(IShape s : shape1) s.draw(); // 空白行 System.out.println(); // Shape 2 for(IShape s : shape2) s.draw(); // 空白行 System.out.println(); // Shape 1 for(IShape s : shape1) s.draw(); // 空白行 System.out.println(); // Shape 2 for(IShape s : shape2) s.draw(); // 空白行 System.out.println(); // Shape 1 for(IShape s : shape1) s.draw(); // 空白行 System.out.println(); // Shape 2 for(IShape s : shape2) s.draw(); } }
instanceof
// 介面一定都是抽象的 import java.util.ArrayList; interface IShape { public void draw(); } interface IWork { public void run(); } // 透過implements來實作介面 class Triangle implements IShape, IWork { public void draw() { System.out.println(" * "); System.out.println(" *** "); } @Override public void run() { System.out.println("Triangle實作run方法"); } } class Rectangle implements IShape { public void draw() { System.out.println("*****"); System.out.println("*****"); } } public class App { public static void main(String[] args) throws Exception { ArrayList<IShape> shapes = new ArrayList<>(); shapes.add(new Triangle()); shapes.add(new Rectangle()); for(IShape s : shapes) { s.draw(); if(s instanceof IWork) { IWork w = (IWork)s; w.run(); } } } }

匿名類別

interface IShape { void draw(); void show(); } // class Triangle implements IShape { // @Override // public void draw() { // System.out.println("draw"); // } // @Override // public void show() { // System.out.println("show"); // } // } public class App { public static void main(String[] args) throws Exception { IShape shape = new IShape() { // 建立實現IShape的匿名物件 @Override public void draw() { System.out.println("draw"); } @Override public void show() { System.out.println("show"); } }; shape.draw(); shape.show(); } }

多執行緒

class JobA { public void doSomething() throws InterruptedException { System.out.println("開始執行JobA"); Thread.sleep(2000); // 暫停2秒鐘 System.out.println("結束執行JobA"); } } class JobB { public void doSomething() throws InterruptedException { System.out.println("開始執行JobB"); Thread.sleep(3000); // 暫停3秒鐘 System.out.println("結束執行JobB"); } } class JobC { public void doSomething() throws InterruptedException { System.out.println("開始執行JobC"); Thread.sleep(4000); // 暫停4秒鐘 System.out.println("結束執行JobC"); } } public class App { public static void main(String[] args) throws Exception { JobA jobA = new JobA(); jobA.doSomething(); JobB jobB = new JobB(); jobB.doSomething(); JobC jobC = new JobC(); jobC.doSomething(); } }

多執行緒版本

// 1. 將要當成多執行緒的類別繼承自Thread類別 // 2. 覆寫run()方法,把要做的事情寫在這個方法內 // 3. 呼叫start()方法來啟動執行緒 import java.util.Date; class JobA extends Thread { public void run() { System.out.println("開始執行JobA"); try { Thread.sleep(2000); } catch (InterruptedException e) { } // 暫停2秒鐘 System.out.println("結束執行JobA"); } } class JobB extends Thread { public void run() { System.out.println("開始執行JobB"); try { Thread.sleep(3000); } catch (InterruptedException e) { } // 暫停3秒鐘 System.out.println("結束執行JobB"); } } class JobC extends Thread { public void run() { System.out.println("開始執行JobC"); try { Thread.sleep(4000); } catch (InterruptedException e) { } // 暫停4秒鐘 System.out.println("結束執行JobC"); } } public class App { public static void main(String[] args) throws Exception { System.out.println("[" + new Date().toString() + "]"); JobA jobA = new JobA(); jobA.start(); // 啟動執行緒 JobB jobB = new JobB(); jobB.start(); JobC jobC = new JobC(); jobC.start(); System.out.println("[" + new Date().toString() + "]"); } }

主要用來等執行緒執行結束

// 1. 將要當成多執行緒的類別繼承自Thread類別 // 2. 覆寫run()方法,把要做的事情寫在這個方法內 // 3. 呼叫start()方法來啟動執行緒 import java.util.ArrayList; import java.util.Date; class JobA extends Thread { public void run() { System.out.println("開始執行JobA"); try { Thread.sleep(2000); } catch (InterruptedException e) { } // 暫停2秒鐘 System.out.println("結束執行JobA"); } } class JobB extends Thread { public void run() { System.out.println("開始執行JobB"); try { Thread.sleep(3000); } catch (InterruptedException e) { } // 暫停3秒鐘 System.out.println("結束執行JobB"); } } class JobC extends Thread { public void run() { System.out.println("開始執行JobC"); try { Thread.sleep(4000); } catch (InterruptedException e) { } // 暫停4秒鐘 System.out.println("結束執行JobC"); } } public class App { public static void main(String[] args) throws Exception { ArrayList<Thread> threads = new ArrayList<>(); System.out.println("[" + new Date().toString() + "]"); JobA jobA = new JobA(); threads.add(jobA); jobA.start(); // 啟動執行緒 JobB jobB = new JobB(); threads.add(jobB); jobB.start(); JobC jobC = new JobC(); threads.add(jobC); jobC.start(); // 暫停等待所有執行緒結束 for(Thread t : threads) { t.join(); } System.out.println("[" + new Date().toString() + "]"); } }

使用Runnable建立執行

// 1. 將要當成多執行緒的類別繼承自Thread類別 // 2. 覆寫run()方法,把要做的事情寫在這個方法內 // 3. 呼叫start()方法來啟動執行緒 import java.util.ArrayList; import java.util.Date; class JobA implements Runnable { public void run() { System.out.println("開始執行JobA"); try { Thread.sleep(2000); } catch (InterruptedException e) { } // 暫停2秒鐘 System.out.println("結束執行JobA"); } } class JobB implements Runnable { public void run() { System.out.println("開始執行JobB"); try { Thread.sleep(3000); } catch (InterruptedException e) { } // 暫停3秒鐘 System.out.println("結束執行JobB"); } } class JobC implements Runnable { public void run() { System.out.println("開始執行JobC"); try { Thread.sleep(4000); } catch (InterruptedException e) { } // 暫停4秒鐘 System.out.println("結束執行JobC"); } } public class App { public static void main(String[] args) throws Exception { ArrayList<Thread> threads = new ArrayList<>(); System.out.println("[" + new Date().toString() + "]"); Thread jobA = new Thread(new JobA()); // 透過Runnable物件來建立Thread物件 threads.add(jobA); jobA.start(); // 啟動執行緒 Thread jobB = new Thread(new JobB()); threads.add(jobB); jobB.start(); Thread jobC = new Thread(new JobC()); threads.add(jobC); jobC.start(); // 暫停等待所有執行緒結束 for(Thread t : threads) { t.join(); } System.out.println("[" + new Date().toString() + "]"); } }

練習

import java.util.Date; class MyThread extends Thread { public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { } App.sum++; } } public class App { public static int sum = 0; public static void main(String[] args) throws Exception { System.out.println("[" + new Date().toString() + "]"); for(int i = 0 ; i < 10 ; i++) { // Thread t = new MyThread(); // t.start(); new MyThread().start(); } // 等待執行緒 System.out.println("總和: " + App.sum); System.out.println("[" + new Date().toString() + "]"); } }

Race Condition

import java.util.ArrayList; import java.util.Date; class MyThread extends Thread { public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { } synchronized(App.sum.getClass()) { App.sum++; } } } public class App { public static Integer sum = 0; public static void main(String[] args) throws Exception { ArrayList<Thread> threads = new ArrayList<>(); System.out.println("[" + new Date().toString() + "]"); for(int i = 0 ; i < 10 ; i++) { // Thread t = new MyThread(); // t.start(); threads.add(new MyThread()); } // 啟動執行緒 for(Thread t : threads) t.start(); // 等待執行緒 for(Thread t : threads) t.join(); System.out.println("總和: " + App.sum); System.out.println("[" + new Date().toString() + "]"); } }