新手向:实现ATM模拟系统
本教程将通过一个完整的ATM模拟系统项目,带你深入了解Java的核心概念和实际应用。
这个ATM系统将涵盖以下功能:
7.2 图形用户界面
使用Java Swing或JavaFX实现图形界面:
import javax.swing.*;public class ATMGUI {public static void main(String[] args) {JFrame frame = new JFrame("ATM系统");// 添加各种GUI组件frame.setSize(400, 300);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);} }
7.3 多语言支持
使用资源束实现国际化:
import java.util.Locale; import java.util.ResourceBundle;ResourceBundle bundle = ResourceBundle.getBundle("Messages", Locale.CHINA); String welcomeMessage = bundle.getString("welcome");
7.4 网络功能
将ATM系统改为客户端-服务器架构:
第八章:常见问题与调试技巧
8.1 并发访问问题
如果多个用户同时访问,需要考虑:
8.3 异常处理
完善异常处理机制:
try {// 可能出错的代码 } catch (SpecificException e) {// 特定异常处理 } catch (Exception e) {// 通用异常处理 } finally {// 清理资源 }
结语:Java学习的进阶
8.2 输入验证
确保所有用户输入都经过验证:
用户登录验证
账户余额查询
存款和取款操作
账户间转账
交易记录查询
密码修改功能
第一章:项目概述与环境搭建
1.1 ATM系统功能分析
我们的ATM模拟系统需要实现以下核心功能:
用户认证:通过卡号和密码验证用户身份
账户管理:包括存款、取款、转账等操作
交易记录:记录所有交易操作并支持查询
安装JDK(建议JDK 8或更高版本)
选择开发工具(IntelliJ IDEA、Eclipse或VS Code)
创建Java项目:
新建一个名为
AdvancedATM
的Java类创建两个辅助类:
BankAccount
和Transaction
密码管理:允许用户修改密码
数据持久化:虽然本示例使用内存存储,但了解数据库连接也很重要
1.2 开发环境准备
与前面的验证码程序一样,我们需要:
安装JDK(建议JDK 8或更高版本)
选择开发工具(IntelliJ IDEA、Eclipse或VS Code)
创建Java项目:
新建一个名为
AdvancedATM
的Java类创建两个辅助类:
BankAccount
和Transaction
第二章:核心类与数据结构设计
2.1 BankAccount类 - 银行账户模型
class BankAccount {private String cardNumber; // 卡号private String pin; // 密码private String holderName; // 持卡人姓名private double balance; // 账户余额private List<Transaction> transactionHistory; // 交易记录// 构造方法public BankAccount(String cardNumber, String pin, String holderName, double balance) {this.cardNumber = cardNumber;this.pin = pin;this.holderName = holderName;this.balance = balance;this.transactionHistory = new ArrayList<>();}// 存款方法public void deposit(double amount) {this.balance += amount;}// 取款方法public boolean withdraw(double amount) {if (amount > balance) {return false;}this.balance -= amount;return true;}// 其他getter和setter方法... }
2.2 Transaction类 - 交易记录模型
class Transaction {private String timestamp; // 交易时间private String description; // 交易描述private double amount; // 交易金额private double balanceAfter; // 交易后余额// 构造方法public Transaction(String timestamp, String description, double amount, double balanceAfter) {this.timestamp = timestamp;this.description = description;this.amount = amount;this.balanceAfter = balanceAfter;}// getter方法... }
2.3 主类AdvancedATM的设计
主类负责整个系统的流程控制,包含以下关键组件:
账户存储:使用
Map
存储所有银行账户交易记录:使用
List
存储所有交易当前账户:跟踪当前登录的用户
日期格式化:统一交易时间格式
输入扫描器:处理用户输入
private static void initializeAccounts() {accounts.put("123456", new BankAccount("123456", "1111", "张三", 5000.0));accounts.put("654321", new BankAccount("654321", "2222", "李四", 10000.0)); }
3.2 登录菜单实现
private static void showLoginMenu() {System.out.println("\n===== ATM 登录系统 =====");System.out.println("1. 登录账户");System.out.println("2. 退出系统");System.out.print("请选择: ");int choice = getIntInput(1, 2);switch (choice) {case 1:login();break;case 2:System.out.println("感谢使用ATM系统,再见!");System.exit(0);} }
3.3 主菜单实现
private static void showMainMenu() {System.out.println("\n===== ATM 主菜单 =====");System.out.println("1. 查询余额");System.out.println("2. 存款");System.out.println("3. 取款");System.out.println("4. 转账");System.out.println("5. 交易记录");System.out.println("6. 修改密码");System.out.println("7. 退出账户");System.out.print("请选择: ");int choice = getIntInput(1, 7);switch (choice) {case 1:checkBalance();break;// 其他case分支...} }
第四章:核心功能实现
4.1 用户登录功能
private static void login() {System.out.println("\n===== 账户登录 =====");System.out.print("请输入卡号: ");String cardNumber = scanner.nextLine();System.out.print("请输入密码: ");String pin = scanner.nextLine();if (accounts.containsKey(cardNumber)) {BankAccount account = accounts.get(cardNumber);if (account.getPin().equals(pin)) {currentAccount = account;System.out.println("登录成功!欢迎," + account.getHolderName());logTransaction("登录系统");} else {System.out.println("密码错误!");}} else {System.out.println("卡号不存在!");} }
4.2 存款功能实现
private static void deposit() {System.out.println("\n===== 存款操作 =====");System.out.print("请输入存款金额: ");double amount = getDoubleInput(0.01, 10000.00);currentAccount.deposit(amount);System.out.printf("存款成功!当前余额: ¥%.2f%n", currentAccount.getBalance());logTransaction("存款", amount); }
4.3 取款功能实现
private static void withdraw() {System.out.println("\n===== 取款操作 =====");System.out.print("请输入取款金额: ");double amount = getDoubleInput(0.01, currentAccount.getBalance());if (currentAccount.withdraw(amount)) {System.out.printf("取款成功!当前余额: ¥%.2f%n", currentAccount.getBalance());logTransaction("取款", -amount);} else {System.out.println("取款失败,余额不足!");} }
4.4 转账功能实现
private static void transfer() {System.out.println("\n===== 转账操作 =====");System.out.print("请输入目标账户卡号: ");String targetCardNumber = scanner.nextLine();if (!accounts.containsKey(targetCardNumber)) {System.out.println("目标账户不存在!");return;}if (targetCardNumber.equals(currentAccount.getCardNumber())) {System.out.println("不能转账给自己!");return;}System.out.print("请输入转账金额: ");double amount = getDoubleInput(0.01, currentAccount.getBalance());BankAccount targetAccount = accounts.get(targetCardNumber);if (currentAccount.withdraw(amount)) {targetAccount.deposit(amount);System.out.printf("转账成功!向 %s 转账 ¥%.2f%n", targetAccount.getHolderName(), amount);System.out.printf("当前余额: ¥%.2f%n", currentAccount.getBalance());logTransaction("转出到 " + targetAccount.getHolderName(), -amount);targetAccount.logTransaction("从 " + currentAccount.getHolderName() + " 转入", amount);} else {System.out.println("转账失败,余额不足!");} }
第五章:辅助功能实现
5.1 交易记录功能
private static void showTransactionHistory() {System.out.println("\n===== 交易记录 =====");System.out.println("时间\t\t\t操作\t\t金额\t\t余额");for (Transaction t : currentAccount.getTransactionHistory()) {System.out.printf("%s\t%s\t\t%s\t%.2f%n",t.getTimestamp(),t.getDescription(),t.getAmount() >= 0 ? "+" + t.getAmount() : t.getAmount(),t.getBalanceAfter());} }
5.2 密码修改功能
private static void changePin() {System.out.println("\n===== 修改密码 =====");System.out.print("请输入当前密码: ");String currentPin = scanner.nextLine();if (!currentAccount.getPin().equals(currentPin)) {System.out.println("当前密码错误!");return;}System.out.print("请输入新密码: ");String newPin = scanner.nextLine();System.out.print("请再次输入新密码: ");String confirmPin = scanner.nextLine();if (!newPin.equals(confirmPin)) {System.out.println("两次输入的密码不一致!");return;}currentAccount.setPin(newPin);System.out.println("密码修改成功!");logTransaction("修改密码"); }
5.3 输入验证工具方法
// 获取整数输入 private static int getIntInput(int min, int max) {while (true) {try {int input = Integer.parseInt(scanner.nextLine());if (input >= min && input <= max) {return input;}System.out.printf("请输入%d-%d之间的数字: ", min, max);} catch (NumberFormatException e) {System.out.print("无效输入,请重新输入: ");}} }// 获取浮点数输入 private static double getDoubleInput(double min, double max) {while (true) {try {double input = Double.parseDouble(scanner.nextLine());if (input >= min && input <= max) {return input;}System.out.printf("请输入%.2f-%.2f之间的金额: ", min, max);} catch (NumberFormatException e) {System.out.print("无效输入,请重新输入: ");}} }
第六章:高级Java概念应用
6.1 集合框架的使用
在本项目中,我们使用了Java集合框架中的两个重要接口:
Map接口:
HashMap
用于存储账户信息private static Map<String, BankAccount> accounts = new HashMap<>();
List接口:
ArrayList
用于存储交易记录private static List<Transaction> transactionHistory = new ArrayList<>();
封装:将数据和操作数据的方法封装在类中
单一职责原则:每个类只负责一个功能领域
开闭原则:对扩展开放,对修改关闭
第七章:项目扩展与改进方向
7.1 数据持久化
当前系统使用内存存储数据,程序退出后数据会丢失。可以改进为:
使用文件存储账户和交易数据
使用数据库(如MySQL)存储数据
实现序列化/反序列化机制
开发服务器端处理业务逻辑
客户端通过网络与服务器通信
使用Socket或RESTful API实现
使用
synchronized
关键字保护共享资源使用并发集合如
ConcurrentHashMap
实现线程安全的数据访问
检查数值范围
处理格式异常
防止SQL注入(如果使用数据库)
结语:Java学习的进阶之路
通过这个ATM模拟系统项目,你已经接触到了Java编程的许多核心概念。接下来可以:
学习Java Web开发(Servlet, JSP, Spring框架)
探索Java网络编程
研究多线程和并发编程
了解设计模式和架构思想
附录:完整ATM系统代码
import java.util.*;
import java.time.*;
import java.time.format.*;public class AdvancedATM {// 账户信息存储private static Map<String, BankAccount> accounts = new HashMap<>();// 交易历史记录private static List<Transaction> transactionHistory = new ArrayList<>();// 当前登录账户private static BankAccount currentAccount = null;// 日期时间格式化private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");// 输入扫描器private static final Scanner scanner = new Scanner(System.in);public static void main(String[] args) {initializeAccounts(); // 初始化测试账户while (true) {if (currentAccount == null) {showLoginMenu();} else {showMainMenu();}}}// 初始化测试账户private static void initializeAccounts() {accounts.put("123456", new BankAccount("123456", "1111", "张三", 5000.0));accounts.put("654321", new BankAccount("654321", "2222", "李四", 10000.0));}// 登录菜单private static void showLoginMenu() {System.out.println("\n===== ATM 登录系统 =====");System.out.println("1. 登录账户");System.out.println("2. 退出系统");System.out.print("请选择: ");int choice = getIntInput(1, 2);switch (choice) {case 1:login();break;case 2:System.out.println("感谢使用ATM系统,再见!");System.exit(0);}}// 主菜单private static void showMainMenu() {System.out.println("\n===== ATM 主菜单 =====");System.out.println("1. 查询余额");System.out.println("2. 存款");System.out.println("3. 取款");System.out.println("4. 转账");System.out.println("5. 交易记录");System.out.println("6. 修改密码");System.out.println("7. 退出账户");System.out.print("请选择: ");int choice = getIntInput(1, 7);switch (choice) {case 1:checkBalance();break;case 2:deposit();break;case 3:withdraw();break;case 4:transfer();break;case 5:showTransactionHistory();break;case 6:changePin();break;case 7:logout();break;}}// 登录功能private static void login() {System.out.println("\n===== 账户登录 =====");System.out.print("请输入卡号: ");String cardNumber = scanner.nextLine();System.out.print("请输入密码: ");String pin = scanner.nextLine();if (accounts.containsKey(cardNumber)) {BankAccount account = accounts.get(cardNumber);if (account.getPin().equals(pin)) {currentAccount = account;System.out.println("登录成功!欢迎," + account.getHolderName());logTransaction("登录系统");} else {System.out.println("密码错误!");}} else {System.out.println("卡号不存在!");}}// 查询余额private static void checkBalance() {System.out.println("\n===== 账户余额 =====");System.out.printf("当前余额: ¥%.2f%n", currentAccount.getBalance());logTransaction("查询余额");}// 存款功能private static void deposit() {System.out.println("\n===== 存款操作 =====");System.out.print("请输入存款金额: ");double amount = getDoubleInput(0.01, 10000.00);currentAccount.deposit(amount);System.out.printf("存款成功!当前余额: ¥%.2f%n", currentAccount.getBalance());logTransaction("存款", amount);}// 取款功能private static void withdraw() {System.out.println("\n===== 取款操作 =====");System.out.print("请输入取款金额: ");double amount = getDoubleInput(0.01, currentAccount.getBalance());if (currentAccount.withdraw(amount)) {System.out.printf("取款成功!当前余额: ¥%.2f%n", currentAccount.getBalance());logTransaction("取款", -amount);} else {System.out.println("取款失败,余额不足!");}}// 转账功能private static void transfer() {System.out.println("\n===== 转账操作 =====");System.out.print("请输入目标账户卡号: ");String targetCardNumber = scanner.nextLine();if (!accounts.containsKey(targetCardNumber)) {System.out.println("目标账户不存在!");return;}if (targetCardNumber.equals(currentAccount.getCardNumber())) {System.out.println("不能转账给自己!");return;}System.out.print("请输入转账金额: ");double amount = getDoubleInput(0.01, currentAccount.getBalance());BankAccount targetAccount = accounts.get(targetCardNumber);if (currentAccount.withdraw(amount)) {targetAccount.deposit(amount);System.out.printf("转账成功!向 %s 转账 ¥%.2f%n", targetAccount.getHolderName(), amount);System.out.printf("当前余额: ¥%.2f%n", currentAccount.getBalance());logTransaction("转出到 " + targetAccount.getHolderName(), -amount);targetAccount.logTransaction("从 " + currentAccount.getHolderName() + " 转入", amount);} else {System.out.println("转账失败,余额不足!");}}// 显示交易记录private static void showTransactionHistory() {System.out.println("\n===== 交易记录 =====");System.out.println("时间\t\t\t操作\t\t金额\t\t余额");for (Transaction t : currentAccount.getTransactionHistory()) {System.out.printf("%s\t%s\t\t%s\t%.2f%n",t.getTimestamp(),t.getDescription(),t.getAmount() >= 0 ? "+" + t.getAmount() : t.getAmount(),t.getBalanceAfter());}}// 修改密码private static void changePin() {System.out.println("\n===== 修改密码 =====");System.out.print("请输入当前密码: ");String currentPin = scanner.nextLine();if (!currentAccount.getPin().equals(currentPin)) {System.out.println("当前密码错误!");return;}System.out.print("请输入新密码: ");String newPin = scanner.nextLine();System.out.print("请再次输入新密码: ");String confirmPin = scanner.nextLine();if (!newPin.equals(confirmPin)) {System.out.println("两次输入的密码不一致!");return;}currentAccount.setPin(newPin);System.out.println("密码修改成功!");logTransaction("修改密码");}// 退出账户private static void logout() {System.out.println("\n正在退出账户...");logTransaction("退出系统");currentAccount = null;}// 记录交易private static void logTransaction(String description) {logTransaction(description, 0);}private static void logTransaction(String description, double amount) {Transaction t = new Transaction(LocalDateTime.now().format(dtf),description,amount,currentAccount.getBalance());currentAccount.addTransaction(t);transactionHistory.add(t);}// 获取整数输入private static int getIntInput(int min, int max) {while (true) {try {int input = Integer.parseInt(scanner.nextLine());if (input >= min && input <= max) {return input;}System.out.printf("请输入%d-%d之间的数字: ", min, max);} catch (NumberFormatException e) {System.out.print("无效输入,请重新输入: ");}}}// 获取浮点数输入private static double getDoubleInput(double min, double max) {while (true) {try {double input = Double.parseDouble(scanner.nextLine());if (input >= min && input <= max) {return input;}System.out.printf("请输入%.2f-%.2f之间的金额: ", min, max);} catch (NumberFormatException e) {System.out.print("无效输入,请重新输入: ");}}}
}// 银行账户类
class BankAccount {private String cardNumber;private String pin;private String holderName;private double balance;private List<Transaction> transactionHistory;public BankAccount(String cardNumber, String pin, String holderName, double balance) {this.cardNumber = cardNumber;this.pin = pin;this.holderName = holderName;this.balance = balance;this.transactionHistory = new ArrayList<>();}// 存款public void deposit(double amount) {this.balance += amount;}// 取款public boolean withdraw(double amount) {if (amount > balance) {return false;}this.balance -= amount;return true;}// 添加交易记录public void addTransaction(Transaction t) {transactionHistory.add(t);}// Getter方法public String getCardNumber() { return cardNumber; }public String getPin() { return pin; }public String getHolderName() { return holderName; }public double getBalance() { return balance; }public List<Transaction> getTransactionHistory() { return transactionHistory; }// Setter方法public void setPin(String pin) { this.pin = pin; }
}// 交易记录类
class Transaction {private String timestamp;private String description;private double amount;private double balanceAfter;public Transaction(String timestamp, String description, double amount, double balanceAfter) {this.timestamp = timestamp;this.description = description;this.amount = amount;this.balanceAfter = balanceAfter;}// Getter方法public String getTimestamp() { return timestamp; }public String getDescription() { return description; }public double getAmount() { return amount; }public double getBalanceAfter() { return balanceAfter; }
}