Java实现简易银行账户管理系统

目录

1、项目概述

1.1 项目结构

1.2 技术栈

2、核心功能说明

2.1 账户管理

2.2 异常处理体系

3、设计理念解析

3.1 面向对象设计

3.2 关键设计点

4、使用指南

4.1 运行流程

4.2 注意事项

5、扩展建议

5.1增加功能

5.2优化方向

6、主要的功能模块代码说明

6.1exception

6.2main

6.3model

6.4utils

7、项目反思

7.1基础设计思路是通用的

7.2框架层面:这是“玩具级”,但能训练核心思维

7.3结论:这是合格的“起点”

1、项目概述

1.1 项目结构

完整代码文件

说明:bin和src的代码目录是一样的,区别在于java中每一个脚本会对应生成一个类文件XX.class存放在bin目录下,对应到的是scr下的java文件

1.2 技术栈
  • 开发环境:Java 17 + Eclipse(其他java编译器都可以)
  • 核心技术:面向对象编程、文件序列化、异常处理
  • 设计模式:策略模式(通过AccountOperations接口)

2、核心功能说明

2.1 账户管理

2.2 异常处理体系
public class BankException extends Exception {  // 自定义异常类public BankException(String message) {super(message);}
}// 使用示例:
try {
    account.withdraw(amount);
} catch (BankException e) {System.out.println(e.getMessage());  // 输出"余额不足"等提示
}

3、设计理念解析

3.1 面向对象设计
classDiagramAccount <|-- CheckingAccountAccount <|-- CreditAccountAccount : +String accountNumberAccount : +double balanceAccount : +deposit(double)Account : +withdraw(double)class CheckingAccount {+double checkingBalance}class CreditAccount {+double creditLimit}

3.2 关键设计点
  1. 抽象与继承
    1. Account抽象类实现AccountOperations接口
    2. CheckingAccountCreditAccount继承父类并重写核心方法
  2. 数据持久化
// 序列化保存
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("accounts.dat"));
oos.writeObject(accounts);// 反序列化加载
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("accounts.dat"));
accounts = (List<Account>) ois.readObject();

      3.模块化设计

module Bank_Management_system {  // 模块化封装requires java.base;requires java.desktop;
}

4、使用指南

4.1 运行流程
  1. 启动程序:运行Main.java
  2. 主菜单操作:

  1. 创建账户示例:
// 储蓄账户
new CheckingAccount("C1001", 5000.0);// 信用账户
new CreditAccount("CR2001", 10000.0, 50000.0);

4.2 注意事项
  1. 账户编号唯一性:系统未做重复校验,需用户自行保证
  2. 数据安全:accounts.dat文件建议定期备份
  3. 异常处理:取款操作必须进行try-catch处理

5、扩展建议

5.1增加功能
    1. 账户转账操作
    2. 交易流水记录
    3. 利息计算功能
5.2优化方向
    1. 使用数据库替代文件存储
    2. 增加图形界面(GUI)
    3. 实现账户编号自动生成

本项目通过约500行代码实现了银行核心业务逻辑,展示了以下软件工程实践:

  • 分层架构设计(模型/工具/异常分层)
  • 高内聚低耦合原则
  • 防御式编程思想
  • 数据持久化解决方案

6、主要的功能模块代码说明

Bank_Management_system\bin\com\bank 下主要的功能模块代码说明

6.1exception

--BankException.java

BankException 是一个自定义异常类,继承自 Java 的 Exception,用于在银行系统中封装特定的错误信息(如余额不足、信用额度不足等),并通过构造函数传递错误描述,使异常处理更加清晰和模块化。

package com.bank.exception;import com.bank.model.AccountOperations;
import com.bank.model.Account;
import com.bank.model.CreditAccount;
import com.bank.model.CheckingAccount;import com.bank.utils.AccountData;import com.bank.exception.BankException;public class BankException extends Exception {public BankException(String message) {super(message);}
}

6.2main

--Main.java

Main 类是银行账户管理系统的入口,通过控制台菜单提供账户创建、存款、取款、余额查询等功能,使用 AccountData 类实现账户数据的加载和保存,并通过 Scanner 与用户交互,确保账户操作的完整性和数据的持久化。

package com.bank.main;import com.bank.model.AccountOperations;
import com.bank.model.Account;
import com.bank.model.CreditAccount;
import com.bank.model.CheckingAccount;import com.bank.utils.AccountData;import com.bank.exception.BankException;import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
import java.io.IOException;public class Main {private static List<Account> accounts = new ArrayList<>();public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int choice = -1;try {
            accounts = AccountData.loadAccounts(); // 从文件中读取账号列表} catch (Exception e) {System.out.println("未发现账户,请创建账户!");}while (choice != 0) {System.out.println("\n欢迎使用银行账户管理系统!");System.out.println("1. 创建账户");System.out.println("2. 存钱操作");System.out.println("3. 取钱操作");System.out.println("4. 显示余额");System.out.println("0. 退出");System.out.print("请选择你要进行的操作:");
            choice = scanner.nextInt();switch (choice) {case 1:createAccount(scanner);break;case 2:processAccount(scanner, true);break;case 3:processAccount(scanner, false);break;case 4:showBalance(scanner);break;case 0:System.out.println("系统退出...");break;default:System.out.println("无效的选择!");}}
        scanner.close();try {AccountData.saveAccounts(accounts); // 把当前账号列表存储到文件中} catch (IOException e) {System.out.println("账户存储失败:" + e.getMessage());
            e.printStackTrace();}}private static void createAccount(Scanner scanner) {System.out.print("请输入账户类型(1: 储蓄账户,2: 信用卡账户):");int accountType = scanner.nextInt();
        scanner.nextLine(); // Consume the newlineSystem.out.print("请输入账户编号:");String accountNumber = scanner.nextLine();if (accountType == 1) {System.out.print("请输入初始余额:");double initialBalance = scanner.nextDouble();Account account = new CheckingAccount(accountNumber, initialBalance);
            accounts.add(account);} else if (accountType == 2) {System.out.print("请输入初始余额:");double initialBalance = scanner.nextDouble();System.out.print("请输入信用额度:");double creditLimit = scanner.nextDouble();Account account = new CreditAccount(accountNumber, initialBalance, creditLimit);
            accounts.add(account);} else {System.out.println("无效的账户类型!");}}private static void processAccount(Scanner scanner, boolean isDeposit) {System.out.print("请输入账户编号:");String accountNumber = scanner.nextLine();Account account = getAccount(accountNumber);if (account == null) {System.out.println("账户不存在!");return;}if (isDeposit) {System.out.print("请输入存款金额:");double amount = scanner.nextDouble();
            account.deposit(amount);} else {System.out.print("请输入取款金额:");double amount = scanner.nextDouble();try {
                account.withdraw(amount);} catch (BankException e) {System.out.println(e.getMessage());}}}private static void showBalance(Scanner scanner) {System.out.print("请输入账户编号:");String accountNumber = scanner.nextLine();Account account = getAccount(accountNumber);if (account == null) {System.out.println("账户不存在!");return;}System.out.println("账户余额:" + account.getBalance());}private static Account getAccount(String accountNumber) {for (Account account : accounts) {if (account.getAccountNumber().equals(accountNumber)) {return account;}}return null;}
}

6.3model

--Account.java

Account 是一个抽象类,实现了 AccountOperations 接口并支持序列化,用于定义银行账户的基本结构(如账户号、余额)和核心操作(存款、取款、查询余额),其中取款操作会检查余额并抛出 BankException 异常,确保账户操作的逻辑完整性和安全性。

package com.bank.model;import java.io.Serializable;import com.bank.model.AccountOperations;
import com.bank.model.Account;
import com.bank.model.CreditAccount;
import com.bank.model.CheckingAccount;import com.bank.utils.AccountData;import com.bank.exception.BankException;public abstract class Account implements AccountOperations, Serializable {protected String accountNumber;protected double balance;public Account(String accountNumber) {this.accountNumber = accountNumber;}@Overridepublic void deposit(double amount) {
        balance += amount;}@Overridepublic void withdraw(double amount) throws BankException {if (balance < amount) {throw new BankException("余额不足");}
        balance -= amount;}@Overridepublic double getBalance() {return balance;}public String getAccountNumber() {return accountNumber;}
}

--AccountOperations.java

AccountOperations 是一个接口,定义了银行账户的核心操作,包括存款 (deposit)、取款 (withdraw) 和查询余额 (getBalance),其中取款操作可能抛出 BankException 异常,确保账户操作的规范性和一致性。

package com.bank.model;import com.bank.model.AccountOperations;
import com.bank.model.Account;
import com.bank.model.CreditAccount;
import com.bank.model.CheckingAccount;import com.bank.utils.AccountData;import com.bank.exception.BankException;public interface AccountOperations {void deposit(double amount);void withdraw(double amount) throws BankException;double getBalance();
}

--CheckingAccount.java

CheckingAccount 是 Account 的子类,专门用于实现储蓄账户的逻辑,重写了存款 (deposit)、取款 (withdraw) 和查询余额 (getBalance) 方法,确保取款时检查存款余额并抛出 BankException 异常,同时通过调用父类方法保持账户余额的一致性。

package com.bank.model;import com.bank.model.AccountOperations;
import com.bank.model.Account;
import com.bank.model.CreditAccount;
import com.bank.model.CheckingAccount;import com.bank.utils.AccountData;import com.bank.exception.BankException;public class CheckingAccount extends Account {// 存款余额private double checkingBalance;public CheckingAccount(String accountNumber, double initialBalance) {super(accountNumber); // 调用父类构造函数,设置账户号码this.checkingBalance = initialBalance;}@Overridepublic void deposit(double amount) {
        checkingBalance += amount;super.deposit(amount); // 调用父类的deposit方法,更新balance属性}@Overridepublic void withdraw(double amount) throws BankException {if (amount > checkingBalance) {throw new BankException("存款余额不足");}
        checkingBalance -= amount;super.withdraw(amount); // 调用父类的withdraw方法,更新balance属性}@Overridepublic double getBalance() {return checkingBalance; // 返回存款余额}
}

--CreditAccount.java

CreditAccount 是 Account 的子类,专门用于实现信用账户的逻辑,支持信用额度 (creditLimit) 的管理,重写了存款 (deposit)、取款 (withdraw) 和查询余额 (getBalance) 方法,确保取款时检查信用额度并抛出 BankException 异常,同时通过调用父类方法保持账户余额的一致性。

package com.bank.model;import com.bank.model.AccountOperations;
import com.bank.model.Account;
import com.bank.model.CreditAccount;
import com.bank.model.CheckingAccount;import com.bank.utils.AccountData;import com.bank.exception.BankException;public class CreditAccount extends Account {// 信用额度private double creditLimit;public CreditAccount(String accountNumber, double initialBalance, double creditLimit) {super(accountNumber); // 调用父类构造函数,设置账户号码this.creditLimit = creditLimit;// 由于信用账户的初始余额可以是负数,我们直接在父类中设置super.deposit(initialBalance); // 调用父类的deposit方法,设置初始余额}@Overridepublic void deposit(double amount) {
        creditLimit += amount;super.deposit(amount); // 调用父类的deposit方法,更新balance属性}@Overridepublic void withdraw(double amount) throws BankException {if (amount > creditLimit) {throw new BankException("信用额度不足");}
        creditLimit -= amount;super.withdraw(amount); // 调用父类的withdraw方法,更新balance属性}@Overridepublic double getBalance() {return super.getBalance(); // 返回父类的balance属性}
}

6.4utils

--AccountData.java

AccountData 是一个工具类,负责银行账户数据的持久化操作,通过序列化将账户列表 (List<Account>) 保存到文件 accounts.dat 中,并通过反序列化从文件中加载账户数据,确保账户信息在程序关闭后仍能保留。

package com.bank.utils;import com.bank.model.Account;
import com.bank.model.CheckingAccount;
import com.bank.model.CreditAccount;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;public class AccountData {private static final String ACCOUNTS_FILE = "accounts.dat";public static List<Account> loadAccounts() throws IOException, ClassNotFoundException {List<Account> accounts = new ArrayList<>();try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(ACCOUNTS_FILE))) {
            accounts = (List<Account>) ois.readObject();}return accounts;}public static void saveAccounts(List<Account> accounts) throws IOException {try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(ACCOUNTS_FILE))) {
            oos.writeObject(accounts);}}
}

7、项目反思

这样比较简易的项目,和实际的开发项目肯定是还差很多,就这个项目来看,里面的设计思路和框架对设计大的项目有用吗

有用,但需要扩展。

这个简易项目的设计思路对大型项目有帮助,但实际开发需要在此基础上大幅升级。核心价值体现在以下几个方面:

7.1基础设计思路是通用的
  • 分层结构model(数据模型)、utils(工具类)、exception(异常处理)的分包方式,是大型项目模块化的雏形。
  • 抽象与继承:用Account抽象类统一管理账户,通过子类实现差异化逻辑,这种面向对象的设计是复杂系统的基础。
  • 异常处理机制:自定义BankException的实践,直接对应企业级开发中的错误处理规范。

但问题也很明显

  • 文件存储(accounts.dat)无法支撑高并发和高数据量,实际项目需要用数据库。
  • 没有日志、单元测试、接口文档等工程化内容。
  • 业务逻辑过于简单(如没有交易流水、权限控制)。

7.2框架层面:这是“玩具级”,但能训练核心思维
  • 优势
    • 你实践了分层设计(数据存储、业务逻辑、异常分离),这是微服务架构的基础。
    • 通过接口(AccountOperations)定义行为,符合依赖倒置原则,后续可以轻松扩展新账户类型。
    • 数据持久化的实现(序列化)帮你理解了状态保存的核心问题。
  • 局限
    • 没有引入任何框架(如Spring),实际项目需要依赖注入、AOP等能力。
    • 模块化(module-info.java)仅停留在语法层面,未体现真正的模块解耦。

7.3结论:这是合格的“起点”
  • 对学习有用:如果你能清晰解释这个项目中为什么用抽象类而不用接口、为什么要序列化、异常为什么要自定义,说明你已经掌握了基础设计思维,也可以熟悉java的代码环境。
  • 对实际项目价值有限:就像学会加减法不等于会解微积分,但加减法是必要基础。要应对复杂系统,还需要学习:
    • 数据库(MySQL/MongoDB)
    • 框架(Spring Boot)
    • 设计模式(工厂、策略、观察者等)
    • 分布式概念(缓存、消息队列)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/6094.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【2024年华为OD机试】(B卷,100分)- 数据分类 (Java JS PythonC/C++)

一、问题描述 题目描述 对一个数据a进行分类,分类方法为: 此数据a(四个字节大小)的四个字节相加对一个给定的值b取模,如果得到的结果小于一个给定的值c,则数据a为有效类型,其类型为取模的值;如果得到的结果大于或者等于c,则数据a为无效类型。 比如一个数据a=0x010…

使用飞桨AI Studio平台训练数据,并进行图像识别分析得牡丹花测试

&#x1f3bc;个人主页&#xff1a;【Y小夜】 &#x1f60e;作者简介&#xff1a;一位双非学校的大二学生&#xff0c;编程爱好者&#xff0c; 专注于基础和实战分享&#xff0c;欢迎私信咨询&#xff01; &#x1f386;入门专栏&#xff1a;&#x1f387;【MySQL&#xff0…

Next.js:构建大模型智能体GPT研究者应用的 Web开发框架

Next.js&#xff1a;构建大模型智能体GPT研究者应用的 Web开发框架 Next.js 基础知识 Next.js 是由 Vercel 公司开发维护的框架&#xff0c;极大地简化了 React 应用的开发流程。其核心特性包括&#xff1a; 服务器端渲染&#xff08;SSR&#xff09;与静态站点生成&#xff…

Redis vs. 其他数据库:深度解析,如何选择最适合的数据库?

一、如何为项目选择合适的数据库&#xff1f; 选择合适的数据库是一个复杂的过程&#xff0c;需要综合考虑多个因素。下面几个维度来详细阐述&#xff1a; 1.数据模型 关系型数据库&#xff08;RDBMS&#xff09;&#xff1a;适用于高度结构化、关联性强的数据&#xff0c;如电…

Linux内存管理(Linux内存架构,malloc,slab的实现)

文章目录 前言一、Linux进程空间内存分配二、malloc的实现机理三、物理内存与虚拟内存1.物理内存2.虚拟内存 四、磁盘和物理内存区别五、页页的基本概念&#xff1a;分页管理的核心概念&#xff1a;Linux 中分页的实现&#xff1a;总结&#xff1a; 六、伙伴算法伙伴算法的核心…

[Computer Vision]实验二:图像特征点提取

目录 一、实验内容 二、实验过程及结果 2.1 Harris角点检测 2.2 SIFT算法 三、实验小结 一、实验内容 采用Harris与SIFT分别提取特征点及对应的描述子&#xff0c;对比两者的区别&#xff08;特征点数量、分布、描述子维度、图像变化对二者的影响等&#xff09;利用特征匹…

运算放大器应用电路设计笔记(六)

6.1输出失调电压发生的原因与计算 6.1.1用噪声增益进行评价 若运算放大器两个输入端接地&#xff0c;则理想运放输出为零&#xff0c;但实际的运放输出不为零&#xff0c;有一定的直流输出电压。这种直流电压称为输出失调电压。发生的原因是&#xff0c;运算放大器内部元件尤…

Ubuntu 24.04 LTS 通过 docker 安装 nextcloud 搭建个人网盘

准备 Ubuntu 24.04 LTSUbuntu 空闲硬盘挂载Ubuntu 安装 Docker DesktopUbuntu 24.04 LTS 安装 tailscale [我的Ubuntu服务器折腾集](https://blog.csdn.net/jh1513/article/details/145222679。 安装 nextcloud 参考 Ubuntu24.04系统Docker安装NextcloudOnlyoffice _。 更…

第18个项目:微信开发入门:获取access_token的Python源码

源码下载地址:https://download.csdn.net/download/mosquito_lover1/90301829 功能特点: 输入AppID和AppSecret,点击按钮后异步获取access_token 1、自动保存功能: 当用户输入或修改 AppID 和 AppSecret 时自动保存 获取到新的 access_token 时自动保存 所有数据都保存在…

基于JAVA的微信点餐小程序设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

基于springboot社区医院管理系统

基于Spring Boot的社区医院管理系统是一个综合性的信息化解决方案&#xff0c;旨在提升社区医院的管理效率、优化医疗服务流程以及增强患者体验。 一、系统背景与目的 随着医疗行业的快速发展和信息化建设的不断推进&#xff0c;社区医院作为基层医疗服务机构&#xff0c;面临…

ChatGPT大模型极简应用开发-CH2-深入了解 GPT-4 和 ChatGPT 的 API

文章目录 2.1 基本概念2.2 OpenAI API 提供的可用模型2.3 在 OpenAI Playground 中使用 GPT模型2.4 开始使用 OpenAI Python 库2.4.1 OpenAI 访问权限和 API 密钥2.4.2 Hello World 示例程序 2.5 使用 GPT-4 和 ChatGPT2.5.1 ChatCompletion 端点的输入选项2.5.2 ChatCompletio…

当使用 npm 时,出现 `certificate has expired` 错误通常意味着请求的证书已过期。

当使用 npm 时&#xff0c;出现 certificate has expired 错误通常意味着请求的证书已过期。这可能是由于以下几种情况&#xff1a; 网络代理问题&#xff1a;如果使用了网络代理&#xff0c;代理服务器的证书可能过期或配置有误。系统时间错误&#xff1a;系统时间不准确可能导…

Android BitmapShader简洁实现马赛克,Kotlin(一)

Android BitmapShader简洁实现马赛克&#xff0c;Kotlin&#xff08;一&#xff09; 这一篇&#xff0c; Android使用PorterDuffXfermode模式PorterDuff.Mode.SRC_OUT橡皮擦实现马赛克效果&#xff0c;Kotlin&#xff08;3&#xff09;-CSDN博客 基于PorterDuffXfermode实现马…

动态内存管理

本章重点 1.为什么存在动态内存分配 2.动态内存函数的介绍 3.malloc free calloc realloc 4.常见的动态内存错误 一.为什么存在动态内存分配 二.动态内存函数的介绍 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include &…

Flutter:搜索页,搜索bar封装

view 使用内置的Chip简化布局 import package:chenyanzhenxuan/common/index.dart; import package:ducafe_ui_core/ducafe_ui_core.dart; import package:flutter/material.dart; import package:get/get.dart; import package:tdesign_flutter/tdesign_flutter.dart;import i…

redis离线安装部署详解(包括一键启动)

像上文一样 因为在学习的过程中没有查到一个详细的离线部署方案 所以在自己学习之后想要自己写一个文章 希望可以帮助后续学习redis离线部署的朋友少走一线弯路 首先就是下载安装包 可以自己在本地下载再传到机器上&#xff08;通过xftp或lrzsz都可&#xff09; http://d…

K8S中Service详解(三)

HeadLiness类型的Service 在某些场景中&#xff0c;开发人员可能不想使用Service提供的负载均衡功能&#xff0c;而希望自己来控制负载均衡策略&#xff0c;针对这种情况&#xff0c;kubernetes提供了HeadLiness Service&#xff0c;这类Service不会分配Cluster IP&#xff0c;…

SpringBoot集成Flink-CDC,实现对数据库数据的监听

一、什么是 CDC &#xff1f; CDC 是Change Data Capture&#xff08;变更数据获取&#xff09;的简称。 核心思想是&#xff0c;监测并捕获数据库的变动&#xff08;包括数据或数据表的插入、 更新以及删除等&#xff09;&#xff0c;将这些变更按发生的顺序完整记录下来&…

2025.1.20——一、[RCTF2015]EasySQL1 二次注入|报错注入|代码审计

题目来源&#xff1a;buuctf [RCTF2015]EasySQL1 目录 一、打开靶机&#xff0c;整理信息 二、解题思路 step 1&#xff1a;初步思路为二次注入&#xff0c;在页面进行操作 step 2&#xff1a;尝试二次注入 step 3&#xff1a;已知双引号类型的字符型注入&#xff0c;构造…