本教程将通过一个完整的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; }
}