ATM 系統是 Java 初學者練習 OOP、異常處理、集合框架、IO 流的經典題目。本文提供一個結構清晰、可直接運行的完整實作,涵蓋賬戶實體、業務邏輯、控制台 UI 與主流程。
package cn.atm;
public class Account {
private final String number;
private final String name;
private String password; // 允許修改密碼
private double balance;
public Account(String number, String name, String password, double balance) {
this.number = number;
this.name = name;
this.password = password;
this.balance = balance;
}
// Getters / Setters 省略
public boolean verifyPassword(String pwd) { return this.password.equals(pwd); }
public void deposit(double amt) { if (amt > 0) balance += amt; }
public boolean withdraw(double amt) { if (amt > 0 && amt <= balance) { balance -= amt; return true; } return false; }
public double getBalance() { return balance; }
}
package cn.atm;
import java.io.*;
import java.util.*;
public class ATMService {
private final Map accounts = new HashMap<>();
private Account currentAccount;
public ATMService() {
// 預設測試賬戶
accounts.put("0000", new Account("0000", "Test User", "0000", 2000.0));
}
public boolean login(String cardNo, String pwd) {
Account acc = accounts.get(cardNo);
if (acc != null && acc.verifyPassword(pwd)) {
currentAccount = acc;
return true;
}
return false;
}
public void deposit(double amt) { currentAccount.deposit(amt); }
public boolean withdraw(double amt) { return currentAccount.withdraw(amt); }
public double queryBalance() { return currentAccount.getBalance(); }
public void showInfo() {
System.out.printf("賬號: %s | 姓名: %s | 餘額: %.2f%n",
currentAccount.getNumber(), currentAccount.getName(), currentAccount.getBalance());
}
}
package cn.atm;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ATMConsole {
private final ATMService service = new ATMService();
private final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public void start() {
System.out.println("=== 歡迎使用 Java ATM 系統 ===");
if (!loginLoop()) return;
mainMenuLoop();
}
private boolean loginLoop() {
for (int i = 0; i < 3; i++) {
try {
System.out.print("請輸入卡號: ");
String card = br.readLine().trim();
System.out.print("請輸入密碼: ");
String pwd = br.readLine().trim();
if (service.login(card, pwd)) {
System.out.println("登入成功!");
return true;
}
System.out.println("卡號或密碼錯誤,剩餘嘗試 " + (2 - i) + " 次");
} catch (IOException e) {
System.err.println("輸入異常: " + e.getMessage());
}
}
System.out.println("嘗試次數過多,系統鎖定。");
return false;
}
private void mainMenuLoop() {
while (true) {
printMenu();
try {
String input = br.readLine().trim();
switch (input) {
case "1" -> withdrawFlow();
case "2" -> service.showInfo();
case "3" -> depositFlow();
case "4" -> { System.out.println("感謝使用,再見!"); return; }
default -> System.out.println("無效選項,請輸入 1-4");
}
} catch (IOException e) {
System.err.println("輸入異常: " + e.getMessage());
}
}
}
private void printMenu() {
System.out.println("\n=== 主選單 ===");
System.out.println("1. 取款");
System.out.println("2. 查詢");
System.out.println("3. 存款");
System.out.println("4. 退出");
System.out.print("請選擇 (1-4): ");
}
private void withdrawFlow() throws IOException {
System.out.print("請輸入取款金額: ");
double amt = Double.parseDouble(br.readLine().trim());
if (service.withdraw(amt)) {
System.out.printf("取款成功,餘額: %.2f%n", service.queryBalance());
} else {
System.out.println("餘額不足或金額無效");
}
}
private void depositFlow() throws IOException {
System.out.print("請輸入存款金額: ");
double amt = Double.parseDouble(br.readLine().trim());
service.deposit(amt);
System.out.printf("存款成功,餘額: %.2f%n", service.queryBalance());
}
public static void main(String[] args) {
new ATMConsole().start();
}
}
=== 歡迎使用 Java ATM 系統 === 請輸入卡號: 0000 請輸入密碼: 0000 登入成功! === 主選單 === 1. 取款 2. 查詢 3. 存款 4. 退出 請選擇 (1-4): 2 賬號: 0000 | 姓名: Test User | 餘額: 2000.00
Transaction 實體,記錄時間、類型、金額、餘額ReentrantLock 守護單賬戶操作,或資料庫樂觀鎖這個迷你 ATM 雖小,卻涵蓋了「實體-服務-表現」分層、異常處理、集合操作、IO 交互等核心技能。建議初學者先跑通、再重構、最後擴展,一步步養成工程化思維。