已複製到剪貼簿!
進度 0%
Java 完整教學課程

掌握 Java 程式設計
從入門到精通

全中文 Java 教學,從基礎語法到進階物件導向,配合豐富的程式碼範例、互動練習與測驗,讓你快速成為 Java 開發高手。

25+
完整章節
100+
程式碼範例
50+
練習題目
免費
完全免費

學習進度追蹤

12%
已完成 3 章 進行中 1 章 未開始 21 章

📌 課程特色

特色
🎯

結構化學習路徑

從零基礎到進階,每章都有清晰的學習目標

💻

互動程式碼範例

每個概念都搭配可執行的完整程式碼

🧩

課後練習測驗

即時測試你的理解程度,鞏固學習效果

📊

進度追蹤系統

記錄你的學習進度,掌握已完成章節

🔍

快速搜尋功能

快速找到你需要的任何Java知識點

🌙

深色/淺色主題

舒適護眼的深色模式,隨時切換

第一章:Java 基礎

基礎
01

什麼是 Java?

入門

Java 是一種 高階、物件導向 的程式語言,由 Sun Microsystems(現為 Oracle)於 1995 年發布。Java 最大的特點是「一次撰寫,到處執行」(Write Once, Run Anywhere),透過 Java 虛擬機器 (JVM) 實現跨平台執行。

  • 📱 Android 行動應用程式 — 全球最多使用者的作業系統
  • 🌐 企業級 Web 應用 — Spring, Jakarta EE 框架
  • 🖥️ 桌面應用程式 — Swing, JavaFX
  • ☁️ 雲端服務與微服務 — 支援大型分散式系統
  • 🎮 遊戲開發 — 如 Minecraft 就是用 Java 開發
  • 🔬 大數據與機器學習 — Hadoop, Spark
特點說明
跨平台同一份程式碼可在 Windows, Mac, Linux 執行
物件導向更好的程式組織方式,易於維護和擴展
強型別在編譯期就能發現大量錯誤,增加安全性
自動記憶體管理垃圾回收機制 (GC),無需手動管理記憶體
龐大生態系數萬個函式庫和框架,解決各種問題
高薪職位Java 開發者需求量全球前三名
  1. 1991 — James Gosling 開始開發 Oak 語言
  2. 1995 — 正式更名為 Java,隨 Netscape 瀏覽器發布
  3. 1996 — Java 1.0 正式釋出
  4. 2004 — Java 5 大幅更新:泛型、列舉、自動裝箱
  5. 2014 — Java 8 引入 Lambda、Stream API
  6. 2018 — 改為每6個月發布一個新版本
  7. 2024 — Java 21 LTS(長期支援版本)發布
💡
JVM、JRE、JDK 的區別
JVM = Java 虛擬機器(執行 bytecode)|JRE = JVM + 執行環境函式庫|JDK = JRE + 開發工具(編譯器等)

第一個 Java 程式

HelloWorld.java
// 這是我的第一個 Java 程式!
public class HelloWorld {
    public static void main(String[] args) {
        // 在控制台輸出文字
        System.out.println("Hello, 世界!歡迎學習 Java!");
        System.out.println("Java 版本:" + System.getProperty("java.version"));
    }
}
// 輸出結果:
Hello, 世界!歡迎學習 Java!
Java 版本:21.0.1
02

Java 開發環境安裝

入門

學習 Java 前,需要安裝 JDK(Java Development Kit)。以下是完整的安裝步驟:

  1. 下載 JDK:前往 Adoptium.net,選擇 Java 21 LTS 版本,根據你的作業系統下載安裝包
  2. 安裝 JDK:執行安裝程式,使用預設設定安裝即可
  3. 設定環境變數:Windows 用戶需將 JDK 的 bin 目錄加入系統 PATH
  4. 驗證安裝:開啟終端機,輸入 java -version 確認安裝成功
  5. 安裝 IDE:推薦使用 IntelliJ IDEA Community(免費)或 VS Code
終端機指令
# 驗證 Java 安裝
java -version
# 驗證編譯器安裝
javac -version

# 編譯 Java 檔案
javac HelloWorld.java

# 執行程式
java HelloWorld
ℹ️
推薦 IDE 比較
IntelliJ IDEA — 功能最強大,適合專業開發 | VS Code — 輕量快速,需安裝 Java 插件 | Eclipse — 老牌 IDE,免費且功能完整
03

Java 基礎語法結構

入門

Java 程式的基本結構包含幾個核心元素。每個 Java 程式都必須有一個類別(Class),並且程式進入點是 main() 方法。

Java 語法結構解析
// 1️⃣ 套件宣告(可選)
package com.example.tutorial;

// 2️⃣ 匯入其他類別(可選)
import java.util.Scanner;

// 3️⃣ 類別定義(必要)- 檔名必須和類別名相同
public class MyFirstProgram {

    // 4️⃣ main 方法 - 程式進入點(必要)
    public static void main(String[] args) {
        
        // 5️⃣ 程式碼區塊
        String message = "Java 學習之旅開始了!";
        System.out.println(message);
        
        // 6️⃣ 每行以分號結尾
        int score = 100;
        System.out.println("分數:" + score);
    }
}

📌 Java 語法重要規則

規則說明範例
區分大小寫Java 對大小寫敏感myVarMyVar
語句以分號結尾每個敘述結尾必須有 ;int x = 5;
大括號定義程式碼區塊{ ... }
類別名首字大寫遵循 PascalCase 命名MyClass
方法名首字小寫遵循 camelCase 命名myMethod()
常數全大寫使用底線分隔MAX_SIZE
04

變數與資料型態

入門

Java 是強型別語言,每個變數都必須宣告其資料型態。Java 有兩大類型:基本型別(Primitive)參考型別(Reference)

型別大小範圍範例
byte1 byte-128 ~ 127byte b = 100;
short2 bytes-32,768 ~ 32,767short s = 5000;
int4 bytes-2^31 ~ 2^31-1int i = 100000;
long8 bytes-2^63 ~ 2^63-1long l = 15000000000L;
float4 bytes6-7 位小數float f = 3.14f;
double8 bytes15 位小數double d = 3.14159;
boolean1 bittrue / falseboolean ok = true;
char2 bytesUnicode 字元char c = 'A';

參考型別儲存的是物件的記憶體位址,而非值本身:

String
字串文字
Integer
int 的包裝類別
Double
double 的包裝類別
Boolean
boolean 包裝類別
Array[]
陣列型別
ArrayList
動態陣列
Object
所有類別的父類
自訂類別
如 Student, Car...
⬆️ 隱式轉換(自動,安全)
int num = 42;
long big = num;   // 自動
double d = num;   // 自動
// byte → short → int
// → long → float → double
⬇️ 顯式轉換(手動,可能失精度)
double d = 3.99;
int i = (int) d; // i = 3

long l = 100L;
int x = (int) l; // x = 100
// 注意:可能溢位!
完整變數宣告範例
public class VariablesDemo {
    public static void main(String[] args) {
        // 基本型別
        int age = 25;
        double salary = 58000.50;
        boolean isStudent = false;
        char grade = 'A';
        
        // 字串(參考型別)
        String name = "張小明";
        
        // final 常數(不可修改)
        final double PI = 3.14159265;
        
        // var 型別推斷(Java 10+)
        var city = "台北";  // 自動推斷為 String
        
        System.out.printf("姓名:%s, 年齡:%d, 薪水:%.2f%n", name, age, salary);
        System.out.println("城市:" + city + ",成績:" + grade);
    }
}
姓名:張小明, 年齡:25, 薪水:58000.50
城市:台北,成績:A
05

運算子大全

入門
運算子名稱範例結果
+加法5 + 38
-減法10 - 46
*乘法3 * 412
/除法10 / 33(整數除法)
%餘數10 % 31
++遞增x++++x+1
--遞減x----x-1
運算子名稱範例結果
==等於5 == 5true
!=不等於5 != 3true
>大於8 > 5true
<小於3 < 7true
>=大於等於5 >= 5true
<=小於等於4 <= 3false
運算子名稱說明範例
&&邏輯 AND兩者都為 true 才回傳 truetrue && false → false
||邏輯 OR其中一個為 true 就回傳 truetrue || false → true
!邏輯 NOT反轉布林值!true → false
運算子等同於範例
+=x = x + nx += 5
-=x = x - nx -= 3
*=x = x * nx *= 2
/=x = x / nx /= 4
%=x = x % nx %= 3

三元運算子是 if-else 的簡短寫法:

三元運算子範例
// 語法:條件 ? 為真時的值 : 為假時的值
int age = 20;
String status = (age >= 18) ? "成年人" : "未成年";
System.out.println(status);  // 成年人

int a = 15, b = 22;
int max = (a > b) ? a : b;
System.out.println("最大值:" + max);  // 最大值:22
06

字串 String 完整教學

入門

在 Java 中,String不可變(immutable)的字元序列,是最常用的資料型態之一。

String 常用方法
public class StringDemo {
    public static void main(String[] args) {
        String s = "Hello, Java!";
        
        // 長度
        System.out.println(s.length());           // 12
        
        // 轉大/小寫
        System.out.println(s.toUpperCase());     // HELLO, JAVA!
        System.out.println(s.toLowerCase());     // hello, java!
        
        // 截取子字串
        System.out.println(s.substring(7));      // Java!
        System.out.println(s.substring(0, 5));  // Hello
        
        // 取代
        System.out.println(s.replace("Java", "World")); // Hello, World!
        
        // 包含/開頭/結尾
        System.out.println(s.contains("Java"));   // true
        System.out.println(s.startsWith("Hello")); // true
        System.out.println(s.endsWith("!"));       // true
        
        // 分割字串
        String[] parts = "A,B,C,D".split(",");
        for (String p : parts) System.out.print(p + " "); // A B C D
        
        // 去除空格
        String trimmed = "  Java  ".trim();  // "Java"
        
        // String.format 格式化
        String msg = String.format("姓名:%s,分數:%d", "小明", 95);
        System.out.println(msg);  // 姓名:小明,分數:95
        
        // StringBuilder - 高效字串拼接
        StringBuilder sb = new StringBuilder();
        sb.append("Hello").append(", ").append("Java!");
        System.out.println(sb.toString());  // Hello, Java!
    }
}
⚠️
字串比較注意!
比較字串內容請用 equals(),而非 ==
== 比較的是記憶體位址,equals() 比較的才是內容。
07

條件判斷:if / switch

入門
if-else 完整範例
public class ConditionDemo {
    public static void main(String[] args) {
        int score = 82;
        
        // if-else if-else
        if (score >= 90) {
            System.out.println("優等 A");
        } else if (score >= 80) {
            System.out.println("良好 B");
        } else if (score >= 70) {
            System.out.println("普通 C");
        } else if (score >= 60) {
            System.out.println("及格 D");
        } else {
            System.out.println("不及格 F");
        }
        
        // switch 語句(傳統)
        String day = "星期三";
        switch (day) {
            case "星期一":
            case "星期二":
            case "星期三":
            case "星期四":
            case "星期五":
                System.out.println("工作日 💼");
                break;
            case "星期六":
            case "星期日":
                System.out.println("假日 🎉");
                break;
            default:
                System.out.println("未知");
        }
        
        // Switch 表達式(Java 14+,更簡潔)
        int month = 3;
        String season = switch (month) {
            case 3, 4, 5  -> "春天 🌸";
            case 6, 7, 8  -> "夏天 ☀️";
            case 9, 10, 11 -> "秋天 🍂";
            default         -> "冬天 ❄️";
        };
        System.out.println(3 + "月是:" + season);
    }
}
良好 B
工作日 💼
3月是:春天 🌸
08

迴圈:for / while / do-while

入門
各種迴圈完整範例
public class LoopDemo {
    public static void main(String[] args) {
        
        // ===== for 迴圈 =====
        System.out.println("=== for 迴圈 ===");
        for (int i = 1; i <= 5; i++) {
            System.out.print(i + " ");
        }
        System.out.println();  // 1 2 3 4 5
        
        // ===== 增強 for 迴圈(for-each)=====
        System.out.println("=== for-each 迴圈 ===");
        String[] fruits = {"蘋果", "香蕉", "橘子", "芒果"};
        for (String fruit : fruits) {
            System.out.print(fruit + " ");
        }
        System.out.println();  // 蘋果 香蕉 橘子 芒果
        
        // ===== while 迴圈 =====
        System.out.println("=== while 迴圈 ===");
        int count = 1;
        while (count <= 5) {
            System.out.print(count * count + " ");
            count++;
        }
        System.out.println();  // 1 4 9 16 25(平方數)
        
        // ===== do-while 迴圈(至少執行一次)=====
        System.out.println("=== do-while 迴圈 ===");
        int n = 0;
        do {
            System.out.print(n + " ");
            n += 2;
        } while (n <= 10);  // 0 2 4 6 8 10
        System.out.println();
        
        // ===== 巢狀迴圈(九九乘法表)=====
        System.out.println("=== 九九乘法表 ===");
        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= 9; j++) {
                System.out.printf("%d×%d=%-3d", i, j, i*j);
            }
            System.out.println();
        }
        
        // ===== break 與 continue =====
        for (int i = 0; i <= 10; i++) {
            if (i == 3) continue; // 跳過 3
            if (i == 7) break;    // 到 7 停止
            System.out.print(i + " ");
        }
        // 0 1 2 4 5 6
    }
}
09

陣列 Array

中級

陣列是用來儲存相同型別多個元素的資料結構,大小固定且索引從 0 開始。

Array 完整操作
import java.util.Arrays;

public class ArrayDemo {
    public static void main(String[] args) {
        // 宣告與初始化
        int[] scores = {85, 92, 78, 95, 88};
        
        // 訪問元素
        System.out.println("第一個:" + scores[0]);  // 85
        System.out.println("最後一個:" + scores[scores.length - 1]); // 88
        
        // 遍歷陣列
        int sum = 0;
        for (int score : scores) sum += score;
        System.out.println("總分:" + sum);
        System.out.printf("平均:%.1f%n", (double) sum / scores.length);
        
        // 排序
        Arrays.sort(scores);
        System.out.println("排序後:" + Arrays.toString(scores));
        
        // 二維陣列
        int[][] matrix = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
        
        System.out.println("二維陣列:");
        for (int[] row : matrix) {
            System.out.println(Arrays.toString(row));
        }
    }
}
第一個:85
最後一個:88
總分:438
平均:87.6
排序後:[78, 85, 88, 92, 95]
二維陣列:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
10

方法 Method(函式)

中級

方法是可重複使用的程式碼區塊,可以接受參數並回傳值,是模組化程式設計的基礎。

方法定義與使用
public class MethodDemo {

    // 無參數、無回傳值
    static void greet() {
        System.out.println("哈囉!歡迎學習 Java!");
    }
    
    // 有參數、有回傳值
    static int add(int a, int b) {
        return a + b;
    }
    
    // 方法多載(Overloading)- 同名但參數不同
    static double add(double a, double b) {
        return a + b;
    }
    
    // 遞迴方法 - 自己呼叫自己
    static int factorial(int n) {
        if (n <= 1) return 1;
        return n * factorial(n - 1);
    }
    
    // 可變長度參數(varargs)
    static int sum(int... numbers) {
        int total = 0;
        for (int n : numbers) total += n;
        return total;
    }
    
    public static void main(String[] args) {
        greet();
        System.out.println("整數相加:" + add(5, 3));
        System.out.println("浮點數相加:" + add(3.14, 2.86));
        System.out.println("5! = " + factorial(5));
        System.out.println("總和:" + sum(1, 2, 3, 4, 5));
    }
}
哈囉!歡迎學習 Java!
整數相加:8
浮點數相加:6.0
5! = 120
總和:15

物件導向程式設計 (OOP)

核心
11

OOP 四大核心概念

中級

物件導向程式設計(Object-Oriented Programming)是 Java 的核心。OOP 以物件(Object)類別(Class)為基礎組織程式碼。

🔒

封裝 Encapsulation

將資料和方法包裝在類別中,使用 private 隱藏細節,用 getter/setter 存取

🧬

繼承 Inheritance

子類別繼承父類別的屬性和方法,透過 extends 實現,促進程式碼重用

🎭

多型 Polymorphism

同一個方法在不同物件中有不同的行為,分為方法覆寫和方法多載

🎨

抽象 Abstraction

隱藏複雜實作細節,只展示必要功能,透過抽象類別和介面實現

12

類別與物件

中級

類別(Class)是物件的藍圖,物件(Object)是類別的實例

類別設計完整範例
// 類別定義(Student.java)
public class Student {
    
    // 屬性(Fields)- 使用 private 封裝
    private String name;
    private int age;
    private double gpa;
    private static int count = 0;  // 靜態變數(類別共用)
    
    // 建構子(Constructor)
    public Student(String name, int age, double gpa) {
        this.name = name;
        this.age = age;
        this.gpa = gpa;
        count++;
    }
    
    // Getter 方法
    public String getName() { return name; }
    public int getAge() { return age; }
    public double getGpa() { return gpa; }
    
    // Setter 方法(帶驗證)
    public void setGpa(double gpa) {
        if (gpa >= 0.0 && gpa <= 4.0) this.gpa = gpa;
        else System.out.println("GPA 無效!");
    }
    
    // 靜態方法
    public static int getCount() { return count; }
    
    // 覆寫 toString 方法
    @Override
    public String toString() {
        return String.format("學生[姓名:%s, 年齡:%d, GPA:%.1f]", name, age, gpa);
    }
    
    // 行為方法
    public void study(String subject) {
        System.out.println(name + " 正在學習 " + subject + "!");
    }
}

// 主程式
public class Main {
    public static void main(String[] args) {
        // 建立物件
        Student s1 = new Student("王小明", 20, 3.8);
        Student s2 = new Student("李小華", 22, 3.5);
        
        System.out.println(s1);  // 呼叫 toString()
        s1.study("Java 程式設計");
        
        System.out.println("學生總數:" + Student.getCount());
    }
}
學生[姓名:王小明, 年齡:20, GPA:3.8]
王小明 正在學習 Java 程式設計!
學生總數:2
13

繼承 Inheritance

中級

繼承允許新類別(子類別)基於現有類別(父類別)建立,使用 extends 關鍵字,實現程式碼重用。

繼承完整範例
// 父類別(Animal)
public class Animal {
    protected String name;
    protected int age;
    
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public void eat() {
        System.out.println(name + " 正在吃東西");
    }
    
    public void makeSound() {
        System.out.println("動物發出聲音...");
    }
}

// 子類別(Dog)繼承 Animal
public class Dog extends Animal {
    private String breed;  // 子類別特有屬性
    
    public Dog(String name, int age, String breed) {
        super(name, age);  // 呼叫父類別建構子
        this.breed = breed;
    }
    
    @Override  // 覆寫父類別方法
    public void makeSound() {
        System.out.println(name + ":汪汪!🐕");
    }
    
    public void fetch() {  // 子類別特有方法
        System.out.println(name + " 去撿球了!");
    }
}

// 子類別(Cat)繼承 Animal
public class Cat extends Animal {
    public Cat(String name, int age) { super(name, age); }
    
    @Override
    public void makeSound() {
        System.out.println(name + ":喵喵~🐱");
    }
}

// 多型示範
Animal[] animals = { new Dog("旺財", 3, "柴犬"), new Cat("咪咪", 2) };
for (Animal a : animals) a.makeSound();
旺財:汪汪!🐕
咪咪:喵喵~🐱
14

介面 Interface & 抽象類別

中級
Interface 與 Abstract Class
// 介面定義
interface Flyable {
    void fly();  // 抽象方法
    default void land() {  // 預設方法(Java 8+)
        System.out.println("降落中...");
    }
}

interface Swimmable {
    void swim();
}

// 抽象類別
abstract class Vehicle {
    protected String brand;
    
    public Vehicle(String brand) { this.brand = brand; }
    
    abstract void move();  // 子類別必須實作
    
    public void info() {  // 具體方法
        System.out.println("品牌:" + brand);
    }
}

// 類別可以 extends 一個類別,implements 多個介面
class Airplane extends Vehicle implements Flyable {
    public Airplane(String brand) { super(brand); }
    
    @Override
    public void move() { System.out.println(brand + " 在滑行"); }
    
    @Override
    public void fly() { System.out.println(brand + " 起飛了!✈️"); }
}

// Duck 實作多個介面
class Duck extends Animal implements Flyable, Swimmable {
    public void fly() { System.out.println("鴨子在飛!"); }
    public void swim() { System.out.println("鴨子在游泳!"); }
}
比較點介面 Interface抽象類別 Abstract
實作implements(可多個)extends(只能一個)
方法預設為 abstract(Java8可有 default)可以有具體方法
變數只能是 static final任意型態
建構子
用途定義行為契約共用基礎實作
15

例外處理 Exception Handling

中級
完整例外處理範例
public class ExceptionDemo {
    
    // 自訂例外類別
    static class AgeException extends Exception {
        public AgeException(String msg) { super(msg); }
    }
    
    static void validateAge(int age) throws AgeException {
        if (age < 0 || age > 150)
            throw new AgeException("年齡 " + age + " 不合理!");
    }
    
    public static void main(String[] args) {
        // try-catch-finally
        try {
            int[] arr = {1, 2, 3};
            System.out.println(arr[10]);  // 拋出例外
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("陣列索引超出範圍: " + e.getMessage());
        } finally {
            System.out.println("finally 區塊必定執行");
        }
        
        // 多重 catch
        try {
            String s = null;
            s.length();  // NullPointerException
        } catch (NullPointerException e) {
            System.out.println("空指標例外!");
        } catch (Exception e) {
            System.out.println("其他例外");
        }
        
        // 自訂例外
        try {
            validateAge(-5);
        } catch (AgeException e) {
            System.out.println("捕獲自訂例外: " + e.getMessage());
        }
        
        // try-with-resources(自動關閉資源)
        try (java.io.FileReader fr = new java.io.FileReader("test.txt")) {
            // 使用資源,結束後自動關閉
        } catch (Exception e) {
            System.out.println("檔案不存在");
        }
    }
}
16

集合框架 Collections Framework

進階

Java 集合框架提供了一組用於儲存和操作物件的通用架構,包含 List、Set、Map、Queue 等。

Collections 全面示範
import java.util.*;
import java.util.stream.*;

public class CollectionsDemo {
    public static void main(String[] args) {
        
        // ===== ArrayList =====
        List<String> fruits = new ArrayList<>();
        fruits.add("蘋果"); fruits.add("香蕉"); fruits.add("芒果");
        fruits.add(1, "橘子");  // 插入到索引 1
        fruits.remove("香蕉");
        System.out.println("List: " + fruits);
        System.out.println("大小:" + fruits.size());
        System.out.println("包含蘋果?" + fruits.contains("蘋果"));
        
        // ===== LinkedList =====
        LinkedList<Integer> queue = new LinkedList<>();
        queue.offer(10); queue.offer(20); queue.offer(30);
        System.out.println("Queue 取出: " + queue.poll());  // 10
        
        // ===== HashSet(不重複)=====
        Set<String> uniqueCities = new HashSet<>();
        uniqueCities.add("台北"); uniqueCities.add("台中");
        uniqueCities.add("台北");  // 重複,不會新增
        System.out.println("Set 大小:" + uniqueCities.size());  // 2
        
        // ===== TreeSet(排序)=====
        Set<Integer> sortedNums = new TreeSet<>(Arrays.asList(5,2,8,1,9));
        System.out.println("排序 Set: " + sortedNums);  // [1, 2, 5, 8, 9]
        
        // ===== HashMap =====
        Map<String, Integer> scores = new HashMap<>();
        scores.put("小明", 95); scores.put("小華", 87); scores.put("小李", 92);
        
        System.out.println("小明的分數:" + scores.get("小明"));
        scores.getOrDefault("小王", 0);  // 不存在時返回 0
        
        // 遍歷 Map
        scores.forEach((k, v) -> System.out.println(k + ": " + v));
        
        // ===== Stream API (Java 8+) =====
        List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        
        int sumOfEvenSquares = numbers.stream()
            .filter(n -> n % 2 == 0)      // 篩選偶數
            .map(n -> n * n)              // 計算平方
            .reduce(0, Integer::sum);     // 求總和
        
        System.out.println("偶數平方和:" + sumOfEvenSquares);  // 220
        
        List<String> filtered = numbers.stream()
            .filter(n -> n > 5)
            .map(n -> "No." + n)
            .collect(Collectors.toList());
        System.out.println(filtered);  // [No.6, No.7, No.8, No.9, No.10]
    }
}
17

Lambda 表達式 & 函數式程式設計

進階

Lambda 表達式(Java 8+)讓你可以用更簡潔的語法表示匿名函數,大幅減少樣板程式碼。

Lambda & 函數式介面
import java.util.*;
import java.util.function.*;

public class LambdaDemo {
    public static void main(String[] args) {
        
        // 傳統寫法 vs Lambda
        Runnable old = new Runnable() {
            @Override
            public void run() { System.out.println("傳統寫法"); }
        };
        Runnable modern = () -> System.out.println("Lambda 寫法 ✨");
        modern.run();
        
        // Predicate - 接收參數,回傳 boolean
        Predicate<Integer> isEven = n -> n % 2 == 0;
        Predicate<String> isLong = s -> s.length() > 5;
        System.out.println(isEven.test(4));    // true
        System.out.println(isLong.test("Hi")); // false
        
        // Function - 接收參數,回傳結果
        Function<String, Integer> strLen = s -> s.length();
        Function<Integer, String> repeat = n -> "*".repeat(n);
        System.out.println(strLen.apply("Hello Java"));  // 10
        System.out.println(repeat.apply(5));              // *****
        
        // Consumer - 接收參數,無回傳
        Consumer<String> print = s -> System.out.println("📌 " + s);
        print.accept("Lambda 很強大!");
        
        // Supplier - 無參數,回傳結果
        Supplier<Double> getRandom = () -> Math.random();
        System.out.printf("隨機數: %.3f%n", getRandom.get());
        
        // 方法引用(Method Reference)
        List<String> names = Arrays.asList("張三", "李四", "王五");
        names.forEach(System.out::println);  // 等同 n -> System.out.println(n)
        
        // 排序使用 Lambda
        List<String> cities = Arrays.asList("台北", "高雄", "台中", "新竹");
        cities.sort((a, b) -> a.compareTo(b));
        System.out.println(cities);
    }
}
18

多執行緒 Multithreading

進階
多執行緒完整範例
import java.util.concurrent.*;

public class ThreadDemo {
    
    // 方法1:繼承 Thread
    static class MyThread extends Thread {
        private String name;
        public MyThread(String name) { this.name = name; }
        
        @Override
        public void run() {
            for (int i = 1; i <= 3; i++) {
                System.out.println(name + " 執行第 " + i + " 次");
                try { Thread.sleep(100); } catch (Exception e) {}
            }
        }
    }
    
    // 方法2:實作 Runnable 介面(推薦)
    static class PrintTask implements Runnable {
        @Override
        public void run() {
            System.out.println("Runnable 在執行:" + Thread.currentThread().getName());
        }
    }
    
    public static void main(String[] args) throws Exception {
        // 建立並啟動執行緒
        MyThread t1 = new MyThread("執行緒A");
        MyThread t2 = new MyThread("執行緒B");
        t1.start(); t2.start();
        
        // Lambda 建立執行緒
        Thread t3 = new Thread(() -> System.out.println("Lambda 執行緒!"));
        t3.start();
        
        // ExecutorService - 執行緒池
        ExecutorService pool = Executors.newFixedThreadPool(4);
        for (int i = 0; i < 5; i++) {
            final int task = i;
            pool.submit(() -> System.out.println("任務 " + task + " 完成"));
        }
        pool.shutdown();
        
        // Callable 和 Future - 有回傳值的執行緒
        ExecutorService exec = Executors.newSingleThreadExecutor();
        Future<Integer> future = exec.submit(() -> {
            Thread.sleep(1000);
            return 42;
        });
        System.out.println("結果:" + future.get());  // 阻塞等待
        exec.shutdown();
    }
}
19

檔案處理 File I/O

進階
檔案讀寫完整範例
import java.io.*;
import java.nio.file.*;
import java.util.*;

public class FileDemo {
    public static void main(String[] args) throws IOException {
        
        // ===== NIO.2 現代寫法(推薦)=====
        Path path = Paths.get("students.txt");
        
        // 寫入文字檔
        List<String> lines = Arrays.asList(
            "王小明,20,A", "李小華,22,B+", "陳小美,21,A-"
        );
        Files.write(path, lines);
        System.out.println("✅ 檔案寫入成功!");
        
        // 讀取所有行
        List<String> content = Files.readAllLines(path);
        content.forEach(line -> System.out.println("📄 " + line));
        
        // 追加內容
        Files.write(path, Arrays.asList("張小龍,23,B"),
            StandardOpenOption.APPEND);
        
        // BufferedReader 逐行讀取(大檔案)
        try (BufferedReader br = Files.newBufferedReader(path)) {
            String line;
            while ((line = br.readLine()) != null) {
                String[] parts = line.split(",");
                System.out.printf("姓名:%-6s 年齡:%s 成績:%s%n",
                    parts[0], parts[1], parts[2]);
            }
        }
        
        // 確認檔案是否存在
        System.out.println("檔案存在:" + Files.exists(path));
        System.out.println("檔案大小:" + Files.size(path) + " bytes");
        
        // 刪除檔案
        Files.delete(path);
        System.out.println("🗑️ 檔案已刪除");
    }
}

📚 完整程式範例庫

範例

精選實用範例

範例
費氏數列(多種方法)
public class Fibonacci {
    // 方法1:遞迴(簡單但慢)
    static long fibRecursive(int n) {
        if (n <= 1) return n;
        return fibRecursive(n-1) + fibRecursive(n-2);
    }
    
    // 方法2:迭代(高效)
    static long fibIterative(int n) {
        if (n <= 1) return n;
        long a = 0, b = 1;
        for (int i = 2; i <= n; i++) {
            long c = a + b; a = b; b = c;
        }
        return b;
    }
    
    public static void main(String[] args) {
        System.out.print("費氏數列: ");
        for (int i = 0; i <= 10; i++)
            System.out.print(fibIterative(i) + " ");
        // 0 1 1 2 3 5 8 13 21 34 55
    }
}
費氏數列: 0 1 1 2 3 5 8 13 21 34 55
氣泡排序 & 快速排序
import java.util.Arrays;

public class SortDemo {
    // 氣泡排序 O(n²)
    static void bubbleSort(int[] arr) {
        int n = arr.length;
        for (int i = 0; i < n-1; i++) {
            for (int j = 0; j < n-i-1; j++) {
                if (arr[j] > arr[j+1]) {
                    int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp;
                }
            }
        }
    }
    
    // 快速排序 O(n log n)
    static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            int pivot = arr[high], i = low - 1;
            for (int j = low; j < high; j++) {
                if (arr[j] <= pivot) {
                    i++;
                    int t = arr[i]; arr[i] = arr[j]; arr[j] = t;
                }
            }
            int t = arr[i+1]; arr[i+1] = arr[high]; arr[high] = t;
            int p = i + 1;
            quickSort(arr, low, p-1);
            quickSort(arr, p+1, high);
        }
    }
    
    public static void main(String[] args) {
        int[] data = {64,34,25,12,22,11,90};
        System.out.println("原始: " + Arrays.toString(data));
        bubbleSort(data);
        System.out.println("排序: " + Arrays.toString(data));
    }
}
原始: [64, 34, 25, 12, 22, 11, 90]
排序: [11, 12, 22, 25, 34, 64, 90]
質數篩選(埃拉托斯特尼篩法)
public class PrimeSieve {
    static boolean[] sieve(int n) {
        boolean[] isPrime = new boolean[n+1];
        Arrays.fill(isPrime, true);
        isPrime[0] = isPrime[1] = false;
        for (int i = 2; i*i <= n; i++) {
            if (isPrime[i])
                for (int j = i*i; j <= n; j += i)
                    isPrime[j] = false;
        }
        return isPrime;
    }
    public static void main(String[] args) {
        boolean[] prime = sieve(50);
        System.out.print("50以內質數: ");
        for (int i = 2; i <= 50; i++)
            if (prime[i]) System.out.print(i + " ");
    }
}
50以內質數: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
銀行帳戶系統(OOP 實戰)
public class BankAccount {
    private String owner;
    private double balance;
    private java.util.List<String> history;
    
    public BankAccount(String owner, double initBalance) {
        this.owner = owner;
        this.balance = initBalance;
        history = new java.util.ArrayList<>();
        history.add("開戶:$" + initBalance);
    }
    
    public synchronized void deposit(double amount) {
        if (amount <= 0) throw new IllegalArgumentException("金額必須為正數");
        balance += amount;
        history.add(String.format("存款 +$%.2f → 餘額 $%.2f", amount, balance));
    }
    
    public synchronized void withdraw(double amount) {
        if (amount > balance) throw new IllegalStateException("餘額不足!");
        balance -= amount;
        history.add(String.format("提款 -$%.2f → 餘額 $%.2f", amount, balance));
    }
    
    public void printStatement() {
        System.out.println("=== " + owner + " 的帳戶明細 ===");
        history.forEach(h -> System.out.println("  " + h));
        System.out.printf("目前餘額:$%.2f%n", balance);
    }
    
    public static void main(String[] args) {
        BankAccount acc = new BankAccount("王小明", 1000.0);
        acc.deposit(500.0);
        acc.deposit(250.0);
        acc.withdraw(200.0);
        acc.printStatement();
    }
}
=== 王小明 的帳戶明細 ===
  開戶:$1000.0
  存款 +$500.00 → 餘額 $1500.00
  存款 +$250.00 → 餘額 $1750.00
  提款 -$200.00 → 餘額 $1550.00
目前餘額:$1550.00

🧩 練習測驗

測驗

問題 1:以下哪個是 Java 中 int 的正確宣告方式?

Ainteger x = 5;
Bint x = 5;
CInt x = 5;
Dint x == 5;

問題 2:在 Java 中,哪個關鍵字用於繼承一個類別?

Aimplements
Binherits
Cextends
Dsuper

問題 3:以下 for 迴圈執行後,輸出為何?
for(int i=0; i<5; i++) System.out.print(i*2+" ");

A1 2 3 4 5
B0 2 4 6 8
C0 1 2 3 4
D2 4 6 8 10

問題 4:ArrayList 和 Array 的主要差異是?

AArrayList 速度更快
BArrayList 大小可動態調整,Array 大小固定
CArrayList 只能存字串
D它們完全相同

🔑 Java 關鍵字速查

參考
關鍵字用途範例
class宣告類別class Student {}
interface宣告介面interface Runnable {}
extends繼承類別class Dog extends Animal
implements實作介面class A implements B
public/private/protected存取修飾符private int age;
static靜態成員(屬於類別)static int count;
final不可修改/繼承/覆寫final int MAX = 100;
abstract抽象類別或方法abstract void draw();
new建立新物件new Student()
this指向目前物件this.name = name;
super指向父類別super(name, age);
return回傳值return total;
void無回傳值void printName()
try/catch/finally例外處理try { } catch(Exception e){}
throws宣告可能拋出的例外void open() throws IOException
import匯入套件import java.util.List;
package宣告套件package com.example;
instanceof檢查物件型別if (obj instanceof String)
synchronized執行緒同步synchronized void method()
volatile確保多執行緒可見性volatile boolean flag;
✨ 感謝學習!繼續加油!