当前位置: 首页 > news >正文

新手向:实现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类

    • 创建两个辅助类:BankAccountTransaction

  • 密码管理:允许用户修改密码

  • 数据持久化:虽然本示例使用内存存储,但了解数据库连接也很重要

    1.2 开发环境准备

    与前面的验证码程序一样,我们需要:

  • 安装JDK(建议JDK 8或更高版本)

  • 选择开发工具(IntelliJ IDEA、Eclipse或VS Code)

  • 创建Java项目

    • 新建一个名为AdvancedATM的Java类

    • 创建两个辅助类:BankAccountTransaction

  • 第二章:核心类与数据结构设计

    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; }
}

http://www.dtcms.com/a/272570.html

相关文章:

  • TDengine 数据库建模最佳实践
  • Oracle 视图
  • Tomcat:Java Web应用的幕后英雄
  • 线性探针是什么:是一种用于探测神经网络中特定特征的工具
  • 从零开始搭建深度学习大厦系列-3.卷积神经网络基础(5-9)
  • 李宏毅(深度学习)--(2)
  • 数据库复合索引设计:为什么等值查询列应该放在范围查询列前面?
  • 区间动态规划详解
  • 【JMeter】跨线程组传递参数
  • 在Docker中运行macOS的超方便体验!
  • SpringAI×Ollama:Java生态无缝集成本地大模型实践指南
  • Redis数据库基础概述
  • 8.2.3希尔排序
  • Spring for Apache Pulsar->Reactive Support->Message Production
  • KV Cache原理详解 + 代码理解
  • 从零实现一个GPT 【React + Express】--- 【2】实现对话流和停止生成
  • Pytest之收集用例规则与运行指定用例
  • 外贸网站模板 网页设计模板网站
  • WinUI3入门17:本地文件存储LocalApplicationData在哪里
  • 【佳易王桌球棋牌计时计费软件】:从功能到实操的全方位解析,灯控器适配、会员管理多场景,软件程序操作教程详解
  • BatchNorm解决梯度消失/爆炸
  • van-tabs 自定义
  • 08-自然壁纸实战教程-视频列表-云
  • softmax公式推导
  • 深度学习中的批处理vs小批量训练
  • 大数据时代UI前端的智能化升级:基于机器学习的用户意图预测
  • MyBatis-Plus的LambdaQuery用法
  • 【音视频】HTTP协议介绍
  • 钉钉拿飞书当靶
  • 测试开发和后端开发到底怎么选?