新手向:实现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; }
}
相关推荐
小小寂寞的城5 分钟前
JAVA策略模式demo【设计模式系列】
java·设计模式·策略模式
阿猿收手吧!21 分钟前
【计算机网络】HTTP1.0 HTTP1.1 HTTP2.0 QUIC HTTP3 究极总结
开发语言·计算机网络
JAVA学习通22 分钟前
图书管理系统(完结版)
java·开发语言
代码老y27 分钟前
Spring Boot项目中大文件上传的高级实践与性能优化
spring boot·后端·性能优化
abigalexy29 分钟前
深入Java锁机制
java
paishishaba29 分钟前
处理Web请求路径参数
java·开发语言·后端
七七七七0730 分钟前
C++类对象多态底层原理及扩展问题
开发语言·c++
神仙别闹31 分钟前
基于Java+MySQL实现(Web)可扩展的程序在线评测系统
java·前端·mysql
程序无bug33 分钟前
Java中的8中基本数据类型转换
java·后端