ATM系统开发
1. 项目介绍
- 就像银行的ATM机子一样:
- 先插卡,也就是登录,输入六位数字密码验证
- 然后,可以选择多样服务:存、取款,转账,查询等一些服务
2. 功能演示
- 以我们目前所学知识,还不足以真的像银行的ATM机子外观效果一样,以后学习更多的Java的API、前端、数据库等知识,就可以做得更完善了
- 目前还是以综合实践,将之前所学知识结合起来使用,这才是我们的目的
(1)项目启动后的首页
- 首页功能:
- 1.登录账户
- 2.注册账户
(2)首页功能演示
- 注册账户功能:
- 一开始是没有账户的,所以需要先注册一个属于你自己的账户:
- 设置账户名称、密码(六位数字)、当次取现额度
- 注册成功后,会随机生成一个8位 0-9 之间的与其他卡号不重复的银行卡号
- 一开始是没有账户的,所以需要先注册一个属于你自己的账户:
- 登录账户功能:
- 注册完账户后,可以进行登录账户的操作:
- 1.需要输入你注册时,得到的银行卡号(八位数字:0-9之间)
- 2.需要输入你注册时,设置的登录密码(六位数字:0-9之间)
- 注册完账户后,可以进行登录账户的操作:
(3)操作页面功能演示
- 操作页面功能:
- 登录成功后,显示操作页面的功能选项:
- 1.查询——>查询账户信息:卡号、户主、余额、当次取现额度
- 2.存款——>存钱
- 3.取款——>取钱
- 4.转账——>转钱给某账户
- 5.修改密码——>修改账户登录密码(六位数:0-9之间)
- 6.退出——>退卡
- 7.注销账户——>删除账户
- 登录成功后,显示操作页面的功能选项:
1: 查询
- 功能1:
- 查询——>查询账户信息:
- 卡号、户主、余额、当次取现额度
- 卡号、户主、余额、当次取现额度
- 查询——>查询账户信息:
2: 存款
- 功能2:
- 存款:
- 1.输入你要存的数额
- 2.存款成功后,显示一下账户信息:卡号、户主、余额、当次取现额度
- 存款:
3: 取款
- 功能3:
- 取款:
- 1.输入你要取的数额:但不能超出每次取款的限额、更不能超出账户余额
- 2.取款成功后,显示一下余额
- 取款:
4/6: 转账、退卡
-
功能4、功能6:
-
转账——>转钱给某账户:
-
1.选择转账的时候,请注意自己的余额,如果自己钱没了,还转毛钱
-
2.没有余额了,先存款,再进行转账
-
3.有钱了,但是系统中只有一个账户,转给谁?
-
4.所以得先退出操作页面(退卡)
-
5.回到首页,再注册一个账户,用于转账
-
6.可以看到:第一个注册的是:黑马武大郎;第二个注册的是黑马武松。接下来就是武大郎给武松转账:
-
登录武大郎账户
-
哥哥给弟弟转账:
- 1.输入对方卡号
- 2.输入对方姓氏:由于是个人信息,所以需要隐蔽
- 3.输入转账的数额:显示一下余额,不能超出余额
- 4.转账成功后,显示一下余额
-
-
-
-
检验武大郎给武松转的钱到账没有:
-
1.先退武大郎的卡
-
2.登录武松的账户,查询余额
-
5: 修改密码
-
功能5:
-
修改当前登录的账户密码:
-
1.输入旧密码验证
-
2.输入两次新密码:要一致
-
3.密码修改成功后,自动退卡,回到首页
-
-
7: 注销账户
-
功能7:
- 注销账户:删除当前登录账户的所有信息
- 注销账户:删除当前登录账户的所有信息
3. 银行ATM系统技术选型分析:
(1)面向对象编程
-
每个用户账户都是一个对象:
- 所以需要设计一个账户类Account用于创建账户对象封装账户信息
(2)使用集合容器
- 系统需要提供一个容器用于存储这些账户对象的信息,我们选用ArrayList集合
- 因为账户的个数不确定,成千上万个账户,集合的大小可变
(3)程序流程控制
- 需要结合分支、循环、跳转关键字等相关操作来控制程序的业务逻辑
(4)使用Java提供的API
- 登录信息的内容比较,业务数据的分析、处理等都需要用到String等常用的API来解决
4. 完成本项目得到的收获
- 优秀的面向对象编程能力;
- 清晰、缜密的业务、数据分析能力;
- 熟练使用程序流程技术来控制计算机完成自己的想法;
- 形成良好的编码习惯,获得一定的编码经验;
- 提升业务分析和解决问题的能力,让基础知识形成体系结构,为后续Java高级技术的学习做有力支撑。
5. 项目完成步骤
(1)系统准备、首页设计
-
分析:
- 首先,每个用户的账户信息都是一个对象,需要设计一个用于封装用户的银行账户信息的账户类;
- 其次,需要提供一个容器用于存储用户开户后的账户信息,集合当然是首选了,因为账户个数不确定、大小可变;
- 最后,首页的设计,两个操作:1.登录账户、2.注册开户;
-
实现:
1.定义实体类: 账户类,用于封装用户的银行账户信息 (1.1) 成员变量: 卡号、姓名、性别、密码、余额、每次取现限额 (1.2) 提供成员变量对应的getter、setter方法,暴露其取值和赋值 (1.3) 提供有参和无参数构造器 2.实现类:ATM系统所有功能的归属地 (2.1) 创建一个账户类型的ArrayList集合,用于存储用户注册开户后的账户对象 (2.2) 创建一个键盘录入对象,用于控制台输入 (2.3) 定义死循环,进入首页: A: 设计首页 B: 用户输入指令; C: 定义switch分支,根据输入的指令进行相应的操作: 1——>登录账户功能: (1) 调用登录账户的方法: 登录账户; (2) 登录成功后,结束switch分支。 2——>注册账户功能: (1) 调用注册开户的方法: 注册账户; (2) 开户成功后,结束switch分支,回到首页 默认——>输入指令有误: (1) 该选项不存在 (2) 结束switch分支,回到首页
-
实体类: 账户类
package com.app; /** 1.定义实体类: 账户类,用于封装用户的银行账户信息 */ public class Account { /** (1.1) 成员变量: 卡号、姓名、性别、密码、余额、每次取现限额 */ private String cardId; private String userName; private String sex; private String password; private double balance; private double amount; /** (1.2) 提供成员变量对应的getter、setter方法,暴露其取值和赋值 */ public String getCardId() { return cardId; } public void setCardId(String cardId) { this.cardId = cardId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } public double getAmount() { return amount; } public void setAmount(double amount) { this.amount = amount; } /** (1.3) 提供有参和无参数构造器 */ public Account() { } public Account(String cardId, String userName, String sex, String password, double balance, double amount) { this.cardId = cardId; this.userName = userName; this.sex = sex; this.password = password; this.balance = balance; this.amount = amount; } }
-
实现类: ATM系统所有功能方法的归属地
package com.app; import java.util.ArrayList; import java.util.Scanner; /** 2.实现类:ATM系统所有功能方法的归属地 */ public class ATMSystemTest { public static void main(String[] args) { // (2.1) 创建一个账户类型的ArrayList集合,用于存储用户注册开户后的账户对象 ArrayList<Account> accounts = new ArrayList<>(); // (2.2) 创建一个键盘录入对象,用于控制台输入 Scanner sc = new Scanner(System.in); // (2.3) 定义死循环,进入首页: while (true) { // A: 设计首页 System.out.println("================ATM系统首页================="); System.out.println("1.登录账户"); System.out.println("2.注册开户"); // B: 用户输入指令 System.out.println("请选择您要办理的业务: "); String command = sc.next(); // C: 定义switch分支,根据输入的指令进行相应的操作: switch (command) { // 1——>登录账户功能 case "1": // (1) 调用userLogin方法: 登录账户 // (2) 登录成功后,结束switch分支 break; // 2——>注册账户功能 case "2": // (1) 调用registerOpenAccount方法: 注册账户 // (2) 开户成功后,结束switch分支,回到首页 break; // 默认——>输入指令有误 default: // (1) 该选项不存在 System.out.println("抱歉~ "+ command + "选项不存在!请重新选择!"); // (2) 结束switch分支,回到首页 break; } } }
(2)用户开户功能实现
-
分析:
- 首先,需要定义一个registerOpenAccount注册开户方法:实现账户信息的录入;
- 其次,需要定义一个getRandomCardId获得卡号的方法:实现随机生成一个8位0-9之间的数 并且 与其他账户不重复的新卡号,需将这个新卡号返回给registerOpenAccount注册开户方法;
- 之后,需要定义一个getAccountByCardId根据卡号查询账户对象的方法:实现根据生成的卡号查询出属于这个卡号的账户对象,需将这个账户对象返回给getRandomCardId获得卡号方法;
- 最后,完成开户。
-
实现:
5.定义registerOpenAccount注册开户方法: 无返回值; 两个形参: 所有账户对象的集合、键盘录入对象; (5.1) 创建一个空的账户对象,用于封装账户信息 (5.2) 录入账户信息: A: 为账户随机一个8位0-9之间 且 与其他账户的卡号不重复的号码(独立写一个方法): (1) 调用getRandomCardId方法,得到一个不重复的8位卡号; (2) 将新卡号存入账户对象中; B: 录入姓名、性别; C: 定义死循环,当两次录入的密码不一致时,重新输入: (1) 输入两次密码; (2) 当第二次输入的密码 与 第一次的密码相等时: a: 两次输入的密码一致: 将输入的密码存入账户对象; b: 密码录入成功,结束循环; (3) 当第二次输入的密码 与 第一次的密码不相等时: a: 两次输入的密码不一致: 重新输入两次密码; D: 余额会在后台默认录入0元; E: 录入账户每次取现的限额; (5.2) 将封装有账户信息的对象添加到集合中; (5.3) 存储好了,说明开户完成,根据性别显示一下姓名和卡号。 6.定义getRandomCardId获得卡号的方法: 返回值类型: String; 一个形参: 所有账户对象的集合; 最终返回一个8位与其他账号不重复的新卡号; (6.1) 创建随机数对象,用于随机生成一个0-9之间的数; (6.2) 定义死循环,为账户随机一个8位0-9之间的数 且 与其他账户的卡号不重复的新号码: A: 定义一个空字符串,用于连接8位卡号数字,得到一个新卡号; B: 定义for循环,循环8次: (1) 每循环一次,就随机生成一个0-9之间的数,并将随机生成的数连接起来; C: 判断这个8位的卡号 是否与 其他账户的卡号 重复了(独立的方法): (1) 调用getAccountByCardId方法: 根据此卡号查询 是否有 属于此卡号的账户对象,并用变量接收查询结果; (2) 当查询结果为空时: a: 说明没有属于此卡号的账户对象,此卡号可以作为新卡号返回; (3) 如果不为空,说明卡号重复了,此卡号不可以作为新卡号返回; while循环会重新执行代码: 生成一个卡号,再判断,直到查询不到重复的卡号,才会进入if,将作为新卡号返回。 7.定义getAccountByCardId根据卡号查询账户对象的方法: 返回值类型: 账户类Account; 两个形参: 所有账户对象的集合、生成的8位卡号; 查询到返回账户对象; 查询不到返回null; (7.1) 定义for循环遍历用于存储开户后的账户对象的集合,得到开户后的所有账户对象: A: 用变量接收得到的账户对象; B: 判断生成的8位卡号 是否 存在于账户对象中; (1) 存在,则返回属于此卡号的账户对象; (7.2) 循环结束,说明查询不到,说明此卡号的账户对象不存在,返回null。
-
注册开户方法:
/** * 5.定义registerOpenAccount注册开户方法: 无返回值 * @param accounts 用于存储开户后的账户对象的集合 * @param sc 键盘录入对象 */ private static void registerOpenAccount(ArrayList<Account> accounts, Scanner sc) { System.out.println("================账户开户界面================="); // (5.1) 创建一个空的账户对象,用于封装账户信息 Account acc = new Account(); // (5.2) 录入账户信息: // A: 为账户随机一个8位0-9之间 且 与其他账户的卡号不重复的号码(独立写一个方法): // (1) 调用getRandomCardId方法,得到一个不重复的8位卡号 String carId = getRandomCardId(accounts); // (2) 将新卡号存入账户对象中 acc.setCardId(carId); // B: 录入姓名、性别; System.out.println("请您输入姓名: "); String userName = sc.next(); System.out.println("请您输入性别: "); String sex = sc.next(); acc.setUserName(userName); acc.setSex(sex); // C: 定义死循环,录入两次密码: while (true) { // (1) 输入两次密码 System.out.println("请您输入6位数的账户密码: "); String newPassword = sc.next(); System.out.println("请您再次确认账户密码: "); String okPassword = sc.next(); // (2) 当第二次输入的密码 与 第一次的密码相等时: if (okPassword.equals(newPassword)) { // a: 两次输入的密码一致: 将输入的密码存入账户对象 acc.setPassword(okPassword); // b: 密码录入成功,结束死循环 break; }else { // (3) 当第二次输入的密码 与 第一次的密码不相等时: // a: 两次输入的密码不一致: 重新输入两次密码 System.out.println("抱歉~ 您两次输入的密码不一致!"); System.out.println(); } } // D: 余额会在后台默认录入0元; // E: 录入账户每次取现的限额 System.out.println("请您输入每次取现限额: "); double amount = sc.nextDouble(); acc.setAmount(amount); // (5.2) 将封装有账户信息的对象添加到集合中 accounts.add(acc); // (5.3) 存储好了,说明开户完成,根据性别显示一下姓名和卡号 System.out.println(sex.equals("男") ? userName + "先生,恭喜您~ 开户完成!您的卡号是: " + carId + ",请妥善保管!" : userName + "女士,恭喜您~ 开户完成!您的卡号是: " + carId + ",请妥善保管!"); System.out.println(); }
-
获得卡号的方法:
/** * 6.定义getRandomCardId获得卡号的方法: 返回值类型: String * @param accounts 用于存储开户后的账户对象的集合 * @return 返回一个8位且与其他账户的卡号不重复的新卡号 */ private static String getRandomCardId(ArrayList<Account> accounts) { // (6.1) 创建随机数对象,用于随机生成一个0-9之间的数 Random rd = new Random(); // (6.2) 定义死循环,为账户随机一个8位0-9之间的数 且 与其他账户的卡号不重复的新号码: while (true) { // A: 定义一个空字符串,用于连接8位卡号数字,得到一个新卡号 String cardId = ""; // B: 定义for循环,循环8次: for (int i = 0; i < 8; i++) { // i = 0 1 2 3 4 5 6 7 // (1) 每循环一次,就随机生成一个0-9之间的数,并将随机生成的数连接起来 cardId += rd.nextInt(10); } // C: 判断这个8位的卡号 是否与 其他账户的卡号 重复了(独立的方法): // (1) 调用getAccountByCardId方法: 根据此卡号查询 是否有 属于此卡号的账户对象,并用变量接收查询结果; Account account = getAccountByCardId(accounts, cardId); // (2) 当查询结果为空时: if (account == null) { // a: 说明没有属于此卡号的账户对象,此卡号可以作为新卡号返回 return cardId; } /* (3) 如果不为空,说明卡号重复了,此卡号不可以作为新卡号返回; while循环会重新执行代码: 生成一个卡号,再判断,直到查询不到重复的卡号,才会进入if,将作为新卡号返回。 */ } }
-
根据卡号查询账户对象的方法:
/** * 7.定义getAccountByCardId根据卡号查询账户对象的方法: 返回值类型: 账户类Account * @param accounts 用于存储开户后的账户对象的集合 * @param cardId 生成的8位0-9之间的数字卡号 * @return 查询到: 返回账户对象; 查询不到: 返回null */ private static Account getAccountByCardId(ArrayList<Account> accounts, String cardId) { // (7.1) 定义for循环遍历用于存储开户后的账户对象的集合,得到开户后的所有账户对象: for (int i = 0; i < accounts.size(); i++) { // A: 用变量接收得到的账户对象 Account account = accounts.get(i); // B: 判断生成的8位卡号 是否 存在于账户对象中 if (cardId.equals(account.getCardId())) { // (1) 存在,则返回属于此卡号的账户对象 return account; } } // (7.2) 循环结束,说明查询不到,说明此卡号的账户对象不存在,返回null return null; }
(3)用户登录功能实现
-
分析:
- 需要定义一个userLogin用户登录的方法:实现用户登录功能;
-
实现:
8.定义userLogin用户登录方法: 无返回值; 两个形参: 所有账户对象的集合、键盘录入对象; (8.1) 当系统中无账户时: a: 温馨提示一下; b: 卫语言风格: 使用return关键字,结束登录方法的执行 (8.2) 当系统中有账户时: A: 定义死循环,当密码输入错误时,重新输入: (1) 输入登录卡号; (2) 调用getAccountByCardId方法,查询该卡号的账户对象,并用变量接收查询结果; (3) 当查询结果为空时: 该卡号不存在; (4) 当查询结果不为空时,说明该卡号存在,可以继续操作: a: 定义死循环,当用户输入的密码不正确时,需重新输入密码: (1) 输入登录密码; (2) 当输入的登录密码正确时: a: 登录成功! b: 登录成功后,调用showUserCommand方法,进入用户操作页面: c: 使用return关键字,结束登录方法的执行; (3) 当输入的登录密码不正确时: a: 登录失败!重新输入。 9.定义showUserCommand用户登录后的操作页面的方法:无返回值;三个形参:所有账户对象的集合、当前登录的账户对象、键盘录入对象; (9.1) 定义死循环,进入用户登录后的操作页面: a: 设计页面; b: 输入操作指令并用变量接收; c: 定义switch分支,根据输入的指令进行相应的操作: 1——查询: a: 调用checkAccount方法,查询账户信息: 卡号、姓名、性别、余额、每次取现限额; b: 查询成功后,结束switch分支,回到操作页面; 2——存款: a: 调用deposit方法,进行存款操作; b: 存款成功后,结束switch分支,回到操作页面; 3——取款: a: 调用getMoney方法,进行取钱操作; b: 取款成功后,结束switch分支,回到操作页面; 4——转账: a: 调用transferMoney方法,进行转账操作; b: 转账成功后,结束switch分支,回到操作页面; 5——修改密码: a: 调用changePassword方法,进行修改密码操作; b: 密码修改成功后,结束操作页面方法的执行,返回上一页; 6——退卡: a: 退卡成功! b: 使用return关键字,结束操作页面方法的执行,回到首页; 7——注销账户: (1) 调用cancelAccount方法,进行注销账户操作: a: 判断用户输入的指令是否为 y: 输入的指令是y,返回true,说明注销成功! (1) 注销成功后,使用return关键字,结束操作页面方法的执行,回到首页; b: 输入的指令不是y,返回false,说明注销失败! (1) 注销失败后,使用break关键字,结束switch分支,回到操作页面; 默认——输入指令有误: a: 该选项不存在! b: 提示完,结束switch分支,回到操作页面;
-
用户登录方法:
/** * 8.定义userLogin用户登录方法: 无返回值 * @param accounts 所有账户对象的集合 * @param sc 键盘录入对象 */ private static void userLogin(ArrayList<Account> accounts, Scanner sc) { // (8.1) 当系统中无账户时: if (accounts.size() == 0) { // a: 温馨提示一下 System.out.println("当前系统无任何账户~ 请先注册开户后再登录!"); System.out.println(); // b: 卫语言风格: 使用return关键字,结束登录方法的执行 return; } // (8.2) 当系统中有账户时: System.out.println("================用户登录界面================="); // A: 定义死循环,进入登录操作页面: while (true) { // (1) 输入登录卡号 System.out.println("请您输入登录的卡号: "); String cardId = sc.next(); // (2) 调用getAccountByCardId方法,查询该卡号的账户对象,并用变量接收查询结果 Account accountByCardId = getAccountByCardId(accounts, cardId); // (3) 当查询结果为空时: if (accountByCardId == null) { // 该卡号不存在 System.out.println("抱歉~ 您输入的卡号不存在!"); }else { // (4) 当查询结果不为空时,说明该卡号存在,可以继续操作: // a: 定义死循环,当用户输入的密码不正确时,需重新输入密码: while (true) { // (1) 输入登录密码 System.out.println("请您输入登录的密码: "); String password = sc.next(); // (2) 当输入的登录密码正确时: if (password.equals(accountByCardId.getPassword())) { // a: 登录成功! System.out.println(accountByCardId.getSex().equals("男") ? accountByCardId.getUserName() + "先生,欢迎您^_^~ 您可以开始办理您的业务了!" : accountByCardId.getUserName() + "女士,欢迎您^_^~ 您可以开始办理您的业务了!"); System.out.println(); // b: 登录成功后,调用showUserCommand方法,进入用户操作页面: showUserCommand(accounts, accountByCardId, sc); // c: 使用return关键字,结束登录方法的执行 return; } else { // (3) 当输入的登录密码不正确时: // a: 登录失败! System.out.println("抱歉~ 您输入的密码不正确!"); } } } } }
-
登录成功后的用户操作界面方法
/** * 9.定义showUserCommand用户登录后的操作页面的方法:无返回值 * @param accounts 所有账户对象的集合 * @param accountByCardId 当前登录卡号的账户对象 * @param sc 键盘录入对象 */ private static void showUserCommand(ArrayList<Account> accounts, Account accountByCardId, Scanner sc) { // (9.1) 定义死循环,进入用户登录后的操作页面: while (true) { // a: 设计页面 System.out.println("================用户操作界面================="); 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.注销账户"); // b: 输入操作指令并用变量接收; System.out.println("请您选择要办理的业务: "); String command = sc.next(); // c: 定义switch分支,根据输入的指令进行相应的操作: switch (command) { // 1——查询 case "1": // a: 调用checkAccount方法,查询账户信息: 卡号、姓名、性别、余额、每次取现限额 checkAccount(accountByCardId); // b: 查询成功后,结束switch分支,回到操作页面 break; // 2——存款 case "2": // a: 调用deposit方法,进行存款操作 deposit(accountByCardId, sc); // b: 存款成功后,结束switch分支,回到操作页面 break; // 3——取款 case "3": // a: 调用getMoney方法,进行取钱操作 getMoney(accountByCardId, sc); // b: 取款成功后,结束switch分支,回到操作页面 break; // 4——转账 case "4": // a: 调用transferMoney方法,进行转账操作 transferMoney(accounts, accountByCardId, sc); // b: 转账成功后,结束switch分支,回到操作页面 break; // 5——修改密码 case "5": // a: 调用changePassword方法,进行修改密码操作 changePassword(accountByCardId, sc); // b: 密码修改成功后,结束操作页面方法的执行,回到首页 return; // 6——退卡 case "6": // a: 退卡成功! System.out.println("您的银行卡已退还,请带走随身物品!欢迎下次光临~"); System.out.println(); // b: 使用return关键字,结束操作页面方法的执行,回到首页 return; // 7——注销账户 case "7": // (1) 调用cancelAccount方法,进行注销账户操作 // a: 判断用户输入的指令是否为 y: if (deleteAccount(accounts, accountByCardId, sc)) { // 输入的指令是y,返回true,说明注销成功! // (1) 注销成功后,使用return关键字,结束操作页面方法的执行,回到首页 return; }else { // b: 输入的指令不是y,返回false,说明注销失败! // (1) 注销失败后,使用break关键字,结束switch分支,回到操作页面 break; } // 默认——输入指令有误 default: // a: 该选项不存在! System.out.println("抱歉~ "+ command +"选项不存在!请重新选择!"); // b: 提示完,结束switch分支,回到操作页面 break; } } }
(4)用户查询功能实现
-
分析:
- 需要定义一个checkAccount查询账户信息的方法:根据登录的卡号查询对应的账户对象,显示该卡号的账户信息;
-
实现:
10.定义checkAccount查询账户信息的方法: 根据登录的卡号查询对应的账户对象,显示该卡号的账户信息; 无返回值; 一个形参: 当前登录卡号的账户对象; (10.1) 显示当前登录的账户信息;
-
查询账户信息的方法:
/** * 10.定义checkAccount查询账户信息的方法:根据登录的卡号查询对应的账户对象,显示该卡号的账户信息 * @param accountByCardId 当前登录卡号的账户对象 */ private static void checkAccount(Account accountByCardId) { // (10.1) 显示该卡号详细的账户信息 System.out.println("----------------您的账户信息----------------"); System.out.println("卡号: " + accountByCardId.getCardId() + "\n" + "户主: " + accountByCardId.getUserName() + "\n" + "性别: " + accountByCardId.getSex() + "\n" + "余额: " + accountByCardId.getBalance() + "元\n" + "每次取现限额: " + accountByCardId.getAmount() + "元"); System.out.println(); }
(5)用户存款、取款、转账功能实现
-
分析:
- 存款:
- 需要定义deposit存款的方法:实现当前登录账户进行存款操作,计算并更新存款后的金额;
- 取款:
- 需要定义getMoney取款的方法:实现当前登录账户进行取款操作,计算并更新取款后的金额
- 转账:
- 需要定义transferMoney转账的方法:实现当前登录账户进行转账操作,计算并更新转账后自己的账户余额 与 对方的账户余额;
- 存款:
-
实现:
11.定义deposit存款方法:无返回值;两个形参:当前登录卡号的账户对象、键盘录入对象; (11.1) 输入存款金额 (11.2) 当输入的存款金额小于100元时: A: 低于100元,不能存; B: 使用return关键字,结束存款方法的执行; (11.3) 当输入的存款金额大于等于100元时: A: 更新账户下的余额: 最新账户余额 = 用账户余额 + 存入的金额; B: 存款成功! C: 存款成功后,调用checkAccount方法: 显示一下账户信息; 12.定义getMoney取款方法:无返回值;两个形参:当前登录卡号的账户对象、键盘录入对象; (12.1) 当账户余额 小于100元时: a: 存款失败! b: 使用return关键字,结束取款方法的执行; (12.2) 定义死循环,进行取钱操作: A: 输入取款金额; B: 当账户余额 大于等于100元时,可以取款: (1) 当取款金额 大于 每次取现限额时: 超出限额啦! (2) 当取款金额 小于等于 每次取现限额时,没有超出限额: a: 当取款金额 大于 账户余额时: 余额不足啦! b: 当取款金额 小于等于 账户余额时,可以取钱: (1) 更新账户余额: 最新账户余额 = 账户余额 - 取款金额; (2) 取款成功,显示一下账户余额; (3) 使用return关键字,结束取款方法的执行; 13.定义transferMoney转账方法:无返回值;三个形参:当前登录卡号的账户对象、所有账户对象的集合、键盘录入对象; (13.1) 当系统账户数量 小于2时: a: 系统中没有其他账户可进行转账; b: 使用return关键字,结束转账方法; (13.2) 当系统账户数量 大于2时,可以下一步操作: A: 当账户余额 小于100元时: 余额不足100元,不能转账; 使用return关键字,结束转账方法的执行; B: 当账户余额 大于100元时,可以转账: (1) 定义死循环,当输入的对方卡号不存在时,重新输入: a: 输入对方的卡号; b: 用户眼花输错成自己的卡号时: 不可以对自己进行转账; 使用continue关键字,结束当次循环的执行,进入下一次循环的执行; c: 用户戴上了眼镜,输入了一个对方的卡号: (1) 调用getAccountByCarId方法,根据输入的对方的卡号查询对方的账户对象,并用变量接收查询结果; (2) 当查询结果为空,说明输入的对方的卡号不存在; 该卡号不存在! (3) 当查询结果不为空,说明查询到对方的账户对象了: a: 将对方姓名的姓氏进行加密操作; b: 通过输入对方的姓氏来确认您是不是认错人了; c: 当输入的对方姓氏无误时: (1) 定义死循环,当用户输入的转账金额 大于 自己的账户余额时,重新输入: a: 输入转账金额; b: 当输入的转账金额 大于 自己账户余额时: 余额不足! c: 当输入的转账金额 小于等于 自己的账户余额时: (1) 更新自己的账户余额 = 自己账户余额 - 转账余额; (2) 更新对方的账户余额 = 对方账户余额 + 转账余额; (3) 转账成功,显示一下自己的账户余额; (4) 使用return关键字,结束转账方法; d: 当输入的对方姓氏有误时: 小心了,可能被诈骗了!
-
存款、取款、转账方法:
/** * 11.定义deposit存款方法:无返回值 * @param accountByCardId 当前登录卡号的账户对象 * @param sc 键盘录入对象 */ private static void deposit(Account accountByCardId, Scanner sc) { System.out.println("================账户存款界面================="); // (11.1) 输入存款金额 System.out.println("请您输入存款金额: "); double money = sc.nextDouble(); // (11.2) 当输入的存款金额小于100元时: if (money < 100) { // A: 低于100元,不能存 System.out.println("抱歉~ 存款金额不能低于100元喔!"); System.out.println(); // B: 使用return关键字,结束存款方法的执行 return; } // (11.3) 当输入的存款金额大于等于100元时: // A: 更新账户下的余额: 最新账户余额 = 用账户余额 + 存入的金额 accountByCardId.setBalance(accountByCardId.getBalance() + money); // B: 存款成功! System.out.println(accountByCardId.getSex().equals("男") ? accountByCardId.getUserName() + "先生^_^,您已存款成功~" : accountByCardId.getUserName() + "女士^_^,您已存款成功~"); System.out.println(); // C: 存款成功后,调用checkAccount方法: 显示一下账户信息 checkAccount(accountByCardId); } /** * 12.定义getMoney取款方法:无返回值 * @param accountByCardId 当前登录卡号的账户对象 * @param sc 键盘录入对象 */ private static void getMoney(Account accountByCardId, Scanner sc) { // (12.1) 当账户余额 小于100元时: if (accountByCardId.getBalance() < 100) { // a: 存款失败! System.out.println("抱歉~ 您的账户余额已不足100元!"); System.out.println(); // b: 使用return关键字,结束取款方法的执行 return; } // (12.2) 定义死循环,进行取钱操作: while (true) { // A: 输入取款金额 System.out.println("================账户取款界面================="); System.out.println("请您输入取款金额: "); double money = sc.nextDouble(); // B: 当账户余额 大于等于100元时,可以取款: if (money > accountByCardId.getAmount()) { // (1) 当取款金额 大于 每次取现限额时: // 超出限额啦! System.out.println("Sorry~ 您当前取款的金额超出了每次取现限额!每次最多可取: " + accountByCardId.getAmount() + "元"); System.out.println(); }else { // (2) 当取款金额 小于等于 每次取现限额时: // a: 当取款金额 大于 账户余额时: if (money > accountByCardId.getBalance()) { // 余额不足啦! System.out.println("Sorry~ 账户余额不足!\t您账户目前的余额为: " + accountByCardId.getBalance() + "元"); System.out.println(); }else { // b: 当取款金额 小于等于 账户余额时,可以取钱: // (1) 更新账户余额: 最新账户余额 = 账户余额 - 取款金额 accountByCardId.setBalance(accountByCardId.getBalance() - money); // (2) 取款成功,显示一下账户余额 System.out.println(money + "元已取走~ 请拿好您的钱和随身物品! \t您账户目前的余额为: " + accountByCardId.getBalance() + "元"); System.out.println(); // (3) 使用return关键字,结束取款方法的执行 return; } } } } /** * 13.定义transferMoney转账方法:无返回值 * @param accountByCardId 当前登录卡号的账户对象 * @param accounts 所有账户对象的集合 * @param sc 键盘录入对象 */ private static void transferMoney(ArrayList<Account> accounts, Account accountByCardId, Scanner sc) { // (13.1) 当系统账户数量 小于2时: if (accounts.size() < 2) { // a: 系统中没有其他账户可进行转账 System.out.println("当前系统中无其他账户可以转账~ 再去注册一个吧!"); System.out.println(); // b: 使用return关键字,结束转账方法 return; } // (13.2) 当系统账户数量 大于2时: // A: 当账户余额 小于100元时: if (accountByCardId.getBalance() < 100) { // 余额不足100元,不能转账 System.out.println("您的账户余额不足100元!您账户目前的余额为: " + accountByCardId.getBalance() + "元!"); System.out.println(); // 使用return关键字,结束转账方法的执行 return; } // B: 当账户余额 大于100元时: // (1) 定义死循环,当输入的对方卡号不存在时,重新输入: System.out.println("================账户转账界面================="); while (true) { // a: 输入对方的卡号 System.out.println("请输入对方的卡号: "); String otherCardId = sc.next(); // b: 用户眼花输错成自己的卡号时: if (accountByCardId.getCardId().equals(otherCardId)) { // 不可以对自己进行转账 System.out.println("抱歉~ 您不可以对自己进行转账喔!"); System.out.println(); // 使用continue关键字,结束当次循环的执行,进入下一次循环的执行 continue; } // c: 用户戴上了眼镜,输入了一个对方的卡号: // (1) 调用getAccountByCarId方法,根据输入的对方的卡号查询对方的账户对象,并用变量接收查询结果 Account otherAcc = getAccountByCardId(accounts, otherCardId); // (2) 当查询结果为空,说明输入的对方的卡号不存在 if (otherAcc == null) { // 该卡号不存在! System.out.println("您输入的转账卡号不存在!请确认!"); System.out.println(); }else { // (3) 当查询结果不为空,说明查询到对方的账户对象了 // a: 将对方姓名的姓氏进行加密操作 String otherName = otherAcc.getUserName().replace(otherAcc.getUserName().substring(0,1), "*"); // b: 通过输入对方的姓氏来确认您是不是认错人了 System.out.println("请您输入[" + otherName + "]的姓氏来确认: "); String lastName = sc.next(); // c: 当输入的对方姓氏无误时: if (lastName.equals(otherAcc.getUserName().substring(0, 1))) { // (1) 定义死循环,当用户输入的转账金额 大于 自己的账户余额时,重新输入: while (true) { // a: 输入转账金额 System.out.println("请您输入转账金额: "); double money = sc.nextDouble(); // b: 当输入的转账金额 大于 自己账户余额时: if (money > accountByCardId.getBalance()) { // 余额不足! System.out.println("您的账户余额不足!您账户目前的余额为: " + accountByCardId.getBalance() + "元!"); System.out.println(); } else { // c: 当输入的转账金额 小于等于 自己的账户余额时: // (1) 更新自己的账户余额 = 自己账户余额 - 转账余额 accountByCardId.setBalance(accountByCardId.getBalance() - money); // (2) 更新对方的账户余额 = 对方账户余额 + 转账余额 otherAcc.setBalance(otherAcc.getBalance() + money); // (3) 转账成功,显示一下自己的账户余额 System.out.println(money + "元已转出~ 您账户目前的余额为: " + accountByCardId.getBalance() + "元!"); System.out.println(); // (4) 使用return关键字,结束转账方法 return; } } } else { // d: 当输入的对方姓氏有误时: // 小心了,可能被诈骗了! System.out.println("您输入的对方姓氏有误!小心被诈骗~"); System.out.println(); } } } }
(6)用户密码修改、注销账户功能实现
-
分析:
- 密码修改:
- 需要定义changePassword修改密码的方法:实现用户修改账户密码的操作,密码修改成功后,自动退出登录;
- 注销账户:
- 需要定义deleteAccount注销账户的方法:实现一键删除当前登录的账户所有信息的操作,注销成功后,自动退出登录;
- 密码修改:
-
实现:
14.定义changePassword修改密码的方法:无返回值;两个形参:当前登录卡号的账户对象、键盘录入对象; (14.1) 定义死循环,当输入的旧密码不正确时,重新输入: A: 输入旧密码; B: 当输入的旧密码无误时: (1) 输入两次新密码; (2) 当两次输入的密码一致时: a: 将输入新密码更新到当前登录的账户信息; b: 使用return关键字,结束密码修改方法的执行; (3) 当两次输入的密码不一致时: 温馨提示一下! C: 当输入的旧密码有误时: 输入的旧密码错误! 15.定义deleteAccount注销账户的方法:返回值类型: boolean;三个形参:所有账户对象的集合、当前登录卡号的账户对象、键盘录入对象; (15.1) 输入指令来确认是否要销户; (15.2) 定义switch分支,根据输入的指令进行相应的操作: y——>注销账户: (1) 当账户余额不为0时: a: 账户有钱,无法销户; (2) 当账户余额为0时,说明账户没钱,可以销户: a: 调用ArrayList集合的API: remove——>从账户集合中删除当前账户对象: 销户; b: 销户成功! c: 销户成功,返回true; (3) 结束switch分支,防止穿透; 默认——>其他指令都视为要保留账户: 保留账户! (15.3) 输入的是其他指令,销户失败!返回false;
-
修改密码、注销账户方法:
/** * 14.定义changePassword修改密码的方法:无返回值 * @param accountByCardId 当前登录卡号的账户对象 * @param sc 键盘录入对象 */ private static void changePassword(Account accountByCardId, Scanner sc) { System.out.println("================密码修改界面================="); // (14.1) 定义死循环,当输入的旧密码不正确时,重新输入: while (true) { // A: 输入旧密码 System.out.println("请您输入旧账户密码: "); String oldPassword = sc.next(); // B: 当输入的旧密码无误时: if (oldPassword.equals(accountByCardId.getPassword())) { // (1) 输入两次新密码 System.out.println("请您输入6位数的新账户密码: "); String newPassword = sc.next(); System.out.println("请您再次确认新账户密码: "); String okPassword = sc.next(); // (2) 当两次输入的密码一致时: if (okPassword.equals(newPassword)) { // a: 将输入新密码更新到当前登录的账户信息 accountByCardId.setPassword(okPassword); System.out.println(accountByCardId.getSex().equals("男") ? accountByCardId.getUserName() + "先生,您的账户密码修改成功~ 请重新登录!" : accountByCardId.getUserName() + "女士,您的账户密码修改成功~ 请重新登录!"); System.out.println(); // b: 使用return关键字,结束密码修改方法的执行 return; }else { // (3) 当两次输入的密码不一致时: // 温馨提示一下! System.out.println("抱歉~ 您两次输入的密码不一致!"); System.out.println(); } }else { // C: 当输入的旧密码有误时: // 输入的旧密码错误! System.out.println("抱歉~ 您输入的旧密码有误!"); System.out.println(); } } } /** * 15.定义deleteAccount注销账户的方法:返回值类型: boolean * @param accounts 所有账户对象的集合 * @param accountByCardId 当前登录卡号的账户对象 * @param sc 键盘录入对象 * @return 销户成功返回true; 销户失败返回false */ private static boolean deleteAccount(ArrayList<Account> accounts, Account accountByCardId, Scanner sc) { System.out.println("================账户注销界面================="); // (15.1) 输入yes 或 其他指令 来确认是否要销户 System.out.println("您真的要销户吗?(y/n): "); String command = sc.next(); // (15.2) 定义switch分支,根据输入的指令进行相应的操作: switch (command) { // y——>注销账户: case "y": // (1) 当账户余额不为0时: if (accountByCardId.getBalance() > 0) { // a: 账户有钱,无法销户 System.out.println("您目前账户还有余额,无法注销! 请将余额全部取出后再注销~"); System.out.println(); }else { // (2) 当账户余额为0时: // a: 调用ArrayList集合的API: remove——>从账户集合中删除当前账户对象: 销户 accounts.remove(accountByCardId); // b: 销户成功! System.out.println("您的账户已注销~ 将无法登录!"); System.out.println(); // c: 销户成功,返回true return true; } // (3) 结束switch分支,防止穿透 break; // 默认——>其他指令都视为要保留账户 default: // 保留账户! System.out.println("好的,您的账户继续保留~"); System.out.println(); } // (15.3) 输入的是其他指令,销户失败!返回false return false; }
最终实现
-
实体类:账户类
package com.app; /** 1.定义实体类: 账户类,用于封装用户的银行账户信息 */ public class Account { /** (1.1) 成员变量: 卡号、姓名、性别、密码、余额、每次取现限额 */ private String cardId; private String userName; private String sex; private String password; private double balance; private double amount; /** (1.2) 提供成员变量对应的getter、setter方法,暴露其取值和赋值 */ public String getCardId() { return cardId; } public void setCardId(String cardId) { this.cardId = cardId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } public double getAmount() { return amount; } public void setAmount(double amount) { this.amount = amount; } /** (1.3) 提供有参和无参数构造器 */ public Account() { } public Account(String cardId, String userName, String sex, String password, double balance, double amount) { this.cardId = cardId; this.userName = userName; this.sex = sex; this.password = password; this.balance = balance; this.amount = amount; } }
-
实现类:所有功能的归属地
package com.app; import java.util.ArrayList; import java.util.Random; import java.util.Scanner; /** 2.实现类:ATM系统所有功能方法的归属地 */ public class ATMSystemTest { public static void main(String[] args) { // (2.1) 创建一个账户类型的ArrayList集合,用于存储用户注册开户后的账户对象 ArrayList<Account> accounts = new ArrayList<>(); // (2.2) 创建一个键盘录入对象,用于控制台输入 Scanner sc = new Scanner(System.in); // (2.3) 定义死循环,进入首页: while (true) { // A: 设计首页 System.out.println("================ATM系统首页================="); System.out.println("1.登录账户"); System.out.println("2.注册开户"); // B: 用户输入指令 System.out.println("请选择您要办理的业务: "); String command = sc.next(); // C: 定义switch分支,根据输入的指令进行相应的操作: switch (command) { // 1——>登录账户功能 case "1": // (1) 调用登录账户的方法: 登录账户 userLogin(accounts, sc); // (2) 登录成功后,结束switch分支 break; // 2——>注册账户功能 case "2": // (1) 调用注册开户的方法: 注册账户 registerOpenAccount(accounts, sc); // (2) 开户成功后,结束switch分支,回到首页 break; // 默认——>输入指令有误 default: // (1) 该选项不存在 System.out.println("抱歉~ "+ command + "选项不存在!请重新选择!"); // (2) 结束switch分支,回到首页 break; } } } /** * 5.定义registerOpenAccount注册开户方法: 无返回值 * @param accounts 用于存储开户后的账户对象的集合 * @param sc 键盘录入对象 */ private static void registerOpenAccount(ArrayList<Account> accounts, Scanner sc) { System.out.println("================账户开户界面================="); // (5.1) 创建一个空的账户对象,用于封装账户信息 Account acc = new Account(); // (5.2) 录入账户信息: // A: 为账户随机一个8位0-9之间 且 与其他账户的卡号不重复的号码(独立写一个方法): // (1) 调用getRandomCardId方法,得到一个不重复的8位卡号 String carId = getRandomCardId(accounts); // (2) 将新卡号存入账户对象中 acc.setCardId(carId); // B: 录入姓名、性别; System.out.println("请您输入姓名: "); String userName = sc.next(); System.out.println("请您输入性别: "); String sex = sc.next(); acc.setUserName(userName); acc.setSex(sex); // C: 定义死循环,录入两次密码: while (true) { // (1) 输入两次密码 System.out.println("请您输入6位数的账户密码: "); String newPassword = sc.next(); System.out.println("请您再次确认账户密码: "); String okPassword = sc.next(); // (2) 当第二次输入的密码 与 第一次的密码相等时: if (okPassword.equals(newPassword)) { // a: 两次输入的密码一致: 将输入的密码存入账户对象 acc.setPassword(okPassword); // b: 密码录入成功,结束死循环 break; }else { // (3) 当第二次输入的密码 与 第一次的密码不相等时: // a: 两次输入的密码不一致: 重新输入两次密码 System.out.println("抱歉~ 您两次输入的密码不一致!"); System.out.println(); } } // D: 余额会在后台默认录入0元; // E: 录入账户每次取现的限额 System.out.println("请您输入每次取现限额: "); double amount = sc.nextDouble(); acc.setAmount(amount); // (5.2) 将封装有账户信息的对象添加到集合中 accounts.add(acc); // (5.3) 存储好了,说明开户完成,根据性别显示一下姓名和卡号 System.out.println(sex.equals("男") ? userName + "先生,恭喜您~ 开户完成!您的卡号是: " + carId + ",请妥善保管!" : userName + "女士,恭喜您~ 开户完成!您的卡号是: " + carId + ",请妥善保管!"); System.out.println(); } /** * 6.定义getRandomCardId获得卡号的方法: 返回值类型: String * @param accounts 用于存储开户后的账户对象的集合 * @return 返回一个8位且与其他账户的卡号不重复的新卡号 */ private static String getRandomCardId(ArrayList<Account> accounts) { // (6.1) 创建随机数对象,用于随机生成一个0-9之间的数 Random rd = new Random(); // (6.2) 定义死循环,为账户随机一个8位0-9之间的数 且 与其他账户的卡号不重复的新号码: while (true) { // A: 定义一个空字符串,用于连接8位卡号数字,得到一个新卡号 String cardId = ""; // B: 定义for循环,循环8次: for (int i = 0; i < 8; i++) { // i = 0 1 2 3 4 5 6 7 // (1) 每循环一次,就随机生成一个0-9之间的数,并将随机生成的数连接起来 cardId += rd.nextInt(10); } // C: 判断这个8位的卡号 是否与 其他账户的卡号 重复了(独立的方法): // (1) 调用getAccountByCardId方法: 根据此卡号查询 是否有 属于此卡号的账户对象,并用变量接收查询结果; Account account = getAccountByCardId(accounts, cardId); // (2) 当查询结果为空时: if (account == null) { // a: 说明没有属于此卡号的账户对象,此卡号可以作为新卡号返回 return cardId; } /* (3) 如果不为空,说明卡号重复了,此卡号不可以作为新卡号返回; while循环会重新执行代码: 生成一个卡号,再判断,直到查询不到重复的卡号,才会进入if,将作为新卡号返回。 */ } } /** * 7.定义getAccountByCardId根据卡号查询账户对象的方法: 返回值类型: 账户类Account * @param accounts 用于存储开户后的账户对象的集合 * @param cardId 生成的8位0-9之间的数字卡号 * @return 查询到: 返回账户对象; 查询不到: 返回null */ private static Account getAccountByCardId(ArrayList<Account> accounts, String cardId) { // (7.1) 定义for循环遍历用于存储开户后的账户对象的集合,得到开户后的所有账户对象: for (int i = 0; i < accounts.size(); i++) { // A: 用变量接收得到的账户对象 Account account = accounts.get(i); // B: 判断生成的8位卡号 是否 存在于账户对象中 if (cardId.equals(account.getCardId())) { // (1) 存在,则返回属于此卡号的账户对象 return account; } } // (7.2) 循环结束,说明查询不到,说明此卡号的账户对象不存在,返回null return null; } /** * 8.定义userLogin用户登录方法: 无返回值 * @param accounts 所有账户对象的集合 * @param sc 键盘录入对象 */ private static void userLogin(ArrayList<Account> accounts, Scanner sc) { // (8.1) 当系统中无账户时: if (accounts.size() == 0) { // a: 温馨提示一下 System.out.println("当前系统无任何账户~ 请先注册开户后再登录!"); System.out.println(); // b: 卫语言风格: 使用return关键字,结束登录方法的执行 return; } // (8.2) 当系统中有账户时: System.out.println("================用户登录界面================="); // A: 定义死循环,进入登录操作页面: while (true) { // (1) 输入登录卡号 System.out.println("请您输入登录的卡号: "); String cardId = sc.next(); // (2) 调用getAccountByCardId方法,查询该卡号的账户对象,并用变量接收查询结果 Account accountByCardId = getAccountByCardId(accounts, cardId); // (3) 当查询结果为空时: if (accountByCardId == null) { // 该卡号不存在 System.out.println("抱歉~ 您输入的卡号不存在!"); }else { // (4) 当查询结果不为空时,说明该卡号存在,可以继续操作: // a: 定义死循环,当用户输入的密码不正确时,需重新输入密码: while (true) { // (1) 输入登录密码 System.out.println("请您输入登录的密码: "); String password = sc.next(); // (2) 当输入的登录密码正确时: if (password.equals(accountByCardId.getPassword())) { // a: 登录成功! System.out.println(accountByCardId.getSex().equals("男") ? accountByCardId.getUserName() + "先生,欢迎您^_^~ 您可以开始办理您的业务了!" : accountByCardId.getUserName() + "女士,欢迎您^_^~ 您可以开始办理您的业务了!"); System.out.println(); // b: 登录成功后,调用showUserCommand方法,进入用户操作页面: showUserCommand(accounts, accountByCardId, sc); // c: 使用return关键字,结束登录方法的执行 return; } else { // (3) 当输入的登录密码不正确时: // a: 登录失败! System.out.println("抱歉~ 您输入的密码不正确!"); } } } } } /** * 9.定义showUserCommand用户登录后的操作页面的方法:无返回值 * @param accounts 所有账户对象的集合 * @param accountByCardId 当前登录卡号的账户对象 * @param sc 键盘录入对象 */ private static void showUserCommand(ArrayList<Account> accounts, Account accountByCardId, Scanner sc) { // (9.1) 定义死循环,进入用户登录后的操作页面: while (true) { // a: 设计页面 System.out.println("================用户操作界面================="); 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.注销账户"); // b: 输入操作指令并用变量接收; System.out.println("请您选择要办理的业务: "); String command = sc.next(); // c: 定义switch分支,根据输入的指令进行相应的操作: switch (command) { // 1——查询 case "1": // a: 调用checkAccount方法,查询账户信息: 卡号、姓名、性别、余额、每次取现限额 checkAccount(accountByCardId); // b: 查询成功后,结束switch分支,回到操作页面 break; // 2——存款 case "2": // a: 调用deposit方法,进行存款操作 deposit(accountByCardId, sc); // b: 存款成功后,结束switch分支,回到操作页面 break; // 3——取款 case "3": // a: 调用getMoney方法,进行取钱操作 getMoney(accountByCardId, sc); // b: 取款成功后,结束switch分支,回到操作页面 break; // 4——转账 case "4": // a: 调用transferMoney方法,进行转账操作 transferMoney(accounts, accountByCardId, sc); // b: 转账成功后,结束switch分支,回到操作页面 break; // 5——修改密码 case "5": // a: 调用changePassword方法,进行修改密码操作 changePassword(accountByCardId, sc); // b: 密码修改成功后,结束操作页面方法的执行,回到首页 return; // 6——退卡 case "6": // a: 退卡成功! System.out.println("您的银行卡已退还,请带走随身物品!欢迎下次光临~"); System.out.println(); // b: 使用return关键字,结束操作页面方法的执行,回到首页 return; // 7——注销账户 case "7": // (1) 调用cancelAccount方法,进行注销账户操作 // a: 判断用户输入的指令是否为 y: if (deleteAccount(accounts, accountByCardId, sc)) { // 输入的指令是y,返回true,说明注销成功! // (1) 注销成功后,使用return关键字,结束操作页面方法的执行,回到首页 return; }else { // b: 输入的指令不是y,返回false,说明注销失败! // (1) 注销失败后,使用break关键字,结束switch分支,回到操作页面 break; } // 默认——输入指令有误 default: // a: 该选项不存在! System.out.println("抱歉~ "+ command +"选项不存在!请重新选择!"); // b: 提示完,结束switch分支,回到操作页面 break; } } } /** * 10.定义checkAccount查询账户信息的方法:根据登录的卡号查询对应的账户对象,显示该卡号的账户信息 * @param accountByCardId 当前登录卡号的账户对象 */ private static void checkAccount(Account accountByCardId) { // (10.1) 显示该卡号详细的账户信息 System.out.println("----------------您的账户信息----------------"); System.out.println("卡号: " + accountByCardId.getCardId() + "\n" + "户主: " + accountByCardId.getUserName() + "\n" + "性别: " + accountByCardId.getSex() + "\n" + "余额: " + accountByCardId.getBalance() + "元\n" + "每次取现限额: " + accountByCardId.getAmount() + "元"); System.out.println(); } /** * 11.定义deposit存款方法:无返回值 * @param accountByCardId 当前登录卡号的账户对象 * @param sc 键盘录入对象 */ private static void deposit(Account accountByCardId, Scanner sc) { System.out.println("================账户存款界面================="); // (11.1) 输入存款金额 System.out.println("请您输入存款金额: "); double money = sc.nextDouble(); // (11.2) 当输入的存款金额小于100元时: if (money < 100) { // A: 低于100元,不能存 System.out.println("抱歉~ 存款金额不能低于100元喔!"); System.out.println(); // B: 使用return关键字,结束存款方法的执行 return; } // (11.3) 当输入的存款金额大于等于100元时: // A: 更新账户下的余额: 最新账户余额 = 用账户余额 + 存入的金额 accountByCardId.setBalance(accountByCardId.getBalance() + money); // B: 存款成功! System.out.println(accountByCardId.getSex().equals("男") ? accountByCardId.getUserName() + "先生^_^,您已存款成功~" : accountByCardId.getUserName() + "女士^_^,您已存款成功~"); System.out.println(); // C: 存款成功后,调用checkAccount方法: 显示一下账户信息 checkAccount(accountByCardId); } /** * 12.定义getMoney取款方法:无返回值 * @param accountByCardId 当前登录卡号的账户对象 * @param sc 键盘录入对象 */ private static void getMoney(Account accountByCardId, Scanner sc) { // (12.1) 当账户余额 小于100元时: if (accountByCardId.getBalance() < 100) { // a: 存款失败! System.out.println("抱歉~ 您的账户余额已不足100元!"); System.out.println(); // b: 使用return关键字,结束取款方法的执行 return; } // (12.2) 定义死循环,进行取钱操作: while (true) { // A: 输入取款金额 System.out.println("================账户取款界面================="); System.out.println("请您输入取款金额: "); double money = sc.nextDouble(); // B: 当账户余额 大于等于100元时,可以取款: if (money > accountByCardId.getAmount()) { // (1) 当取款金额 大于 每次取现限额时: // 超出限额啦! System.out.println("Sorry~ 您当前取款的金额超出了每次取现限额!每次最多可取: " + accountByCardId.getAmount() + "元"); System.out.println(); }else { // (2) 当取款金额 小于等于 每次取现限额时: // a: 当取款金额 大于 账户余额时: if (money > accountByCardId.getBalance()) { // 余额不足啦! System.out.println("Sorry~ 账户余额不足!\t您账户目前的余额为: " + accountByCardId.getBalance() + "元"); System.out.println(); }else { // b: 当取款金额 小于等于 账户余额时,可以取钱: // (1) 更新账户余额: 最新账户余额 = 账户余额 - 取款金额 accountByCardId.setBalance(accountByCardId.getBalance() - money); // (2) 取款成功,显示一下账户余额 System.out.println(money + "元已取走~ 请拿好您的钱和随身物品! \t您账户目前的余额为: " + accountByCardId.getBalance() + "元"); System.out.println(); // (3) 使用return关键字,结束取款方法的执行 return; } } } } /** * 13.定义transferMoney转账方法:无返回值 * @param accountByCardId 当前登录卡号的账户对象 * @param accounts 所有账户对象的集合 * @param sc 键盘录入对象 */ private static void transferMoney(ArrayList<Account> accounts, Account accountByCardId, Scanner sc) { // (13.1) 当系统账户数量 小于2时: if (accounts.size() < 2) { // a: 系统中没有其他账户可进行转账 System.out.println("当前系统中无其他账户可以转账~ 再去注册一个吧!"); System.out.println(); // b: 使用return关键字,结束转账方法 return; } // (13.2) 当系统账户数量 大于2时: // A: 当账户余额 小于100元时: if (accountByCardId.getBalance() < 100) { // 余额不足100元,不能转账 System.out.println("您的账户余额不足100元!您账户目前的余额为: " + accountByCardId.getBalance() + "元!"); System.out.println(); // 使用return关键字,结束转账方法的执行 return; } // B: 当账户余额 大于100元时: // (1) 定义死循环,当输入的对方卡号不存在时,重新输入: System.out.println("================账户转账界面================="); while (true) { // a: 输入对方的卡号 System.out.println("请输入对方的卡号: "); String otherCardId = sc.next(); // b: 用户眼花输错成自己的卡号时: if (accountByCardId.getCardId().equals(otherCardId)) { // 不可以对自己进行转账 System.out.println("抱歉~ 您不可以对自己进行转账喔!"); System.out.println(); // 使用continue关键字,结束当次循环的执行,进入下一次循环的执行 continue; } // c: 用户戴上了眼镜,输入了一个对方的卡号: // (1) 调用getAccountByCarId方法,根据输入的对方的卡号查询对方的账户对象,并用变量接收查询结果 Account otherAcc = getAccountByCardId(accounts, otherCardId); // (2) 当查询结果为空,说明输入的对方的卡号不存在 if (otherAcc == null) { // 该卡号不存在! System.out.println("您输入的转账卡号不存在!请确认!"); System.out.println(); }else { // (3) 当查询结果不为空,说明查询到对方的账户对象了 // a: 将对方姓名的姓氏进行加密操作 String otherName = otherAcc.getUserName().replace(otherAcc.getUserName().substring(0,1), "*"); // b: 通过输入对方的姓氏来确认您是不是认错人了 System.out.println("请您输入[" + otherName + "]的姓氏来确认: "); String lastName = sc.next(); // c: 当输入的对方姓氏无误时: if (lastName.equals(otherAcc.getUserName().substring(0, 1))) { // (1) 定义死循环,当用户输入的转账金额 大于 自己的账户余额时,重新输入: while (true) { // a: 输入转账金额 System.out.println("请您输入转账金额: "); double money = sc.nextDouble(); // b: 当输入的转账金额 大于 自己账户余额时: if (money > accountByCardId.getBalance()) { // 余额不足! System.out.println("您的账户余额不足!您账户目前的余额为: " + accountByCardId.getBalance() + "元!"); System.out.println(); } else { // c: 当输入的转账金额 小于等于 自己的账户余额时: // (1) 更新自己的账户余额 = 自己账户余额 - 转账余额 accountByCardId.setBalance(accountByCardId.getBalance() - money); // (2) 更新对方的账户余额 = 对方账户余额 + 转账余额 otherAcc.setBalance(otherAcc.getBalance() + money); // (3) 转账成功,显示一下自己的账户余额 System.out.println(money + "元已转出~ 您账户目前的余额为: " + accountByCardId.getBalance() + "元!"); System.out.println(); // (4) 使用return关键字,结束转账方法 return; } } } else { // d: 当输入的对方姓氏有误时: // 小心了,可能被诈骗了! System.out.println("您输入的对方姓氏有误!小心被诈骗~"); System.out.println(); } } } } /** * 14.定义changePassword修改密码的方法:无返回值 * @param accountByCardId 当前登录卡号的账户对象 * @param sc 键盘录入对象 */ private static void changePassword(Account accountByCardId, Scanner sc) { System.out.println("================密码修改界面================="); // (14.1) 定义死循环,当输入的旧密码不正确时,重新输入: while (true) { // A: 输入旧密码 System.out.println("请您输入旧账户密码: "); String oldPassword = sc.next(); // B: 当输入的旧密码无误时: if (oldPassword.equals(accountByCardId.getPassword())) { // (1) 输入两次新密码 System.out.println("请您输入6位数的新账户密码: "); String newPassword = sc.next(); System.out.println("请您再次确认新账户密码: "); String okPassword = sc.next(); // (2) 当两次输入的密码一致时: if (okPassword.equals(newPassword)) { // a: 将输入新密码更新到当前登录的账户信息 accountByCardId.setPassword(okPassword); System.out.println(accountByCardId.getSex().equals("男") ? accountByCardId.getUserName() + "先生,您的账户密码修改成功~ 请重新登录!" : accountByCardId.getUserName() + "女士,您的账户密码修改成功~ 请重新登录!"); System.out.println(); // b: 使用return关键字,结束密码修改方法的执行 return; }else { // (3) 当两次输入的密码不一致时: // 温馨提示一下! System.out.println("抱歉~ 您两次输入的密码不一致!"); System.out.println(); } }else { // C: 当输入的旧密码有误时: // 输入的旧密码错误! System.out.println("抱歉~ 您输入的旧密码有误!"); System.out.println(); } } } /** * 15.定义deleteAccount注销账户的方法:返回值类型: boolean * @param accounts 所有账户对象的集合 * @param accountByCardId 当前登录卡号的账户对象 * @param sc 键盘录入对象 * @return 销户成功返回true; 销户失败返回false */ private static boolean deleteAccount(ArrayList<Account> accounts, Account accountByCardId, Scanner sc) { System.out.println("================账户注销界面================="); // (15.1) 输入yes 或 其他指令 来确认是否要销户 System.out.println("您真的要销户吗?(y/n): "); String command = sc.next(); // (15.2) 定义switch分支,根据输入的指令进行相应的操作: switch (command) { // y——>注销账户: case "y": // (1) 当账户余额不为0时: if (accountByCardId.getBalance() > 0) { // a: 账户有钱,无法销户 System.out.println("您目前账户还有余额,无法注销! 请将余额全部取出后再注销~"); System.out.println(); }else { // (2) 当账户余额为0时: // a: 调用ArrayList集合的API: remove——>从账户集合中删除当前账户对象: 销户 accounts.remove(accountByCardId); // b: 销户成功! System.out.println("您的账户已注销~ 将无法登录!"); System.out.println(); // c: 销户成功,返回true return true; } // (3) 结束switch分支,防止穿透 break; // 默认——>其他指令都视为要保留账户 default: // 保留账户! System.out.println("好的,您的账户继续保留~"); System.out.println(); } // (15.3) 输入的是其他指令,销户失败!返回false return false; } }
-
控制台:看效果
================ATM系统首页================= 1.登录账户 2.注册开户 请选择您要办理的业务: 1 当前系统无任何账户~ 请先注册开户后再登录! ================ATM系统首页================= 1.登录账户 2.注册开户 请选择您要办理的业务: 2 ================账户开户界面================= 请您输入姓名: 张无忌 请您输入性别: 男 请您输入6位数的账户密码: 112233 请您再次确认账户密码: 1122333 抱歉~ 您两次输入的密码不一致! 请您输入6位数的账户密码: 112233 请您再次确认账户密码: 112233 请您输入每次取现限额: 7000 张无忌先生,恭喜您~ 开户完成!您的卡号是: 26854428,请妥善保管! ================ATM系统首页================= 1.登录账户 2.注册开户 请选择您要办理的业务: 3 抱歉~ 3选项不存在!请重新选择! ================ATM系统首页================= 1.登录账户 2.注册开户 请选择您要办理的业务: 1 ================用户登录界面================= 请您输入登录的卡号: 268544283223 抱歉~ 您输入的卡号不存在! 请您输入登录的卡号: 26854428 请您输入登录的密码: 123123 抱歉~ 您输入的密码不正确! 请您输入登录的密码: 112233 张无忌先生,欢迎您^_^~ 您可以开始办理您的业务了! ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 1 ----------------您的账户信息---------------- 卡号: 26854428 户主: 张无忌 性别: 男 余额: 0.0元 每次取现限额: 7000.0元 ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 3 抱歉~ 您的账户余额已不足100元! ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 2 ================账户存款界面================= 请您输入存款金额: 5000 张无忌先生^_^,您已存款成功~ ----------------您的账户信息---------------- 卡号: 26854428 户主: 张无忌 性别: 男 余额: 5000.0元 每次取现限额: 7000.0元 ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 3 ================账户取款界面================= 请您输入取款金额: 5500 Sorry~ 账户余额不足! 您账户目前的余额为: 5000.0元 ================账户取款界面================= 请您输入取款金额: 8000 Sorry~ 您当前取款的金额超出了每次取现限额!每次最多可取: 7000.0元 ================账户取款界面================= 请您输入取款金额: 5000 5000.0元已取走~ 请拿好您的钱和随身物品! 您账户目前的余额为: 0.0元 ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 3 抱歉~ 您的账户余额已不足100元! ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 4 当前系统中无其他账户可以转账~ 再去注册一个吧! ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 6 您的银行卡已退还,请带走随身物品!欢迎下次光临~ ================ATM系统首页================= 1.登录账户 2.注册开户 请选择您要办理的业务: 2 ================账户开户界面================= 请您输入姓名: 周芷若 请您输入性别: 女 请您输入6位数的账户密码: 123123 请您再次确认账户密码: 123123 请您输入每次取现限额: 5000 周芷若女士,恭喜您~ 开户完成!您的卡号是: 73785031,请妥善保管! ================ATM系统首页================= 1.登录账户 2.注册开户 请选择您要办理的业务: 1 ================用户登录界面================= 请您输入登录的卡号: 73785031 请您输入登录的密码: 123123 周芷若女士,欢迎您^_^~ 您可以开始办理您的业务了! ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 1 ----------------您的账户信息---------------- 卡号: 73785031 户主: 周芷若 性别: 女 余额: 0.0元 每次取现限额: 5000.0元 ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 2 ================账户存款界面================= 请您输入存款金额: 400 周芷若女士^_^,您已存款成功~ ----------------您的账户信息---------------- 卡号: 73785031 户主: 周芷若 性别: 女 余额: 400.0元 每次取现限额: 5000.0元 ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 6 您的银行卡已退还,请带走随身物品!欢迎下次光临~ ================ATM系统首页================= 1.登录账户 2.注册开户 请选择您要办理的业务: 1 ================用户登录界面================= 请您输入登录的卡号: 26854428 请您输入登录的密码: 112233 张无忌先生,欢迎您^_^~ 您可以开始办理您的业务了! ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 4 您的账户余额不足100元!您账户目前的余额为: 0.0元! ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 2 ================账户存款界面================= 请您输入存款金额: 20000 张无忌先生^_^,您已存款成功~ ----------------您的账户信息---------------- 卡号: 26854428 户主: 张无忌 性别: 男 余额: 20000.0元 每次取现限额: 7000.0元 ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 4 ================账户转账界面================= 请输入对方的卡号: 26854428 抱歉~ 您不可以对自己进行转账喔! 请输入对方的卡号: 737850314324 您输入的转账卡号不存在!请确认! 请输入对方的卡号: 73785031 请您输入[*芷若]的姓氏来确认: 老 您输入的对方姓氏有误!小心被诈骗~ 请输入对方的卡号: 73785031 请您输入[*芷若]的姓氏来确认: 周 请您输入转账金额: 4000000 您的账户余额不足!您账户目前的余额为: 20000.0元! 请您输入转账金额: 20000 20000.0元已转出~ 您账户目前的余额为: 0.0元! ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 5 ================密码修改界面================= 请您输入旧账户密码: 666666 抱歉~ 您输入的旧密码有误! 请您输入旧账户密码: 112233 请您输入6位数的新账户密码: 666666 请您再次确认新账户密码: 6666666 抱歉~ 您两次输入的密码不一致! 请您输入旧账户密码: 112233 请您输入6位数的新账户密码: 777777 请您再次确认新账户密码: 77777 抱歉~ 您两次输入的密码不一致! 请您输入旧账户密码: 112233 请您输入6位数的新账户密码: 112211 请您再次确认新账户密码: 112211 张无忌先生,您的账户密码修改成功~ 请重新登录! ================ATM系统首页================= 1.登录账户 2.注册开户 请选择您要办理的业务: 1 ================用户登录界面================= 请您输入登录的卡号: 26854428 请您输入登录的密码: 112233 抱歉~ 您输入的密码不正确! 请您输入登录的密码: 112211 张无忌先生,欢迎您^_^~ 您可以开始办理您的业务了! ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 7 ================账户注销界面================= 您真的要销户吗?(y/n): n 好的,您的账户继续保留~ ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 7 ================账户注销界面================= 您真的要销户吗?(y/n): y 您的账户已注销~ 将无法登录! ================ATM系统首页================= 1.登录账户 2.注册开户 请选择您要办理的业务: 1 ================用户登录界面================= 请您输入登录的卡号: 26854428 抱歉~ 您输入的卡号不存在! 请您输入登录的卡号: 73785031 请您输入登录的密码: 123123 周芷若女士,欢迎您^_^~ 您可以开始办理您的业务了! ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 1 ----------------您的账户信息---------------- 卡号: 73785031 户主: 周芷若 性别: 女 余额: 20400.0元 每次取现限额: 5000.0元 ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 7 ================账户注销界面================= 您真的要销户吗?(y/n): y 您目前账户还有余额,无法注销! 请将余额全部取出后再注销~ ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 3 ================账户取款界面================= 请您输入取款金额: 5000 5000.0元已取走~ 请拿好您的钱和随身物品! 您账户目前的余额为: 15400.0元 ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 3 ================账户取款界面================= 请您输入取款金额: 5000 5000.0元已取走~ 请拿好您的钱和随身物品! 您账户目前的余额为: 10400.0元 ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 3 ================账户取款界面================= 请您输入取款金额: 5000 5000.0元已取走~ 请拿好您的钱和随身物品! 您账户目前的余额为: 5400.0元 ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 4 当前系统中无其他账户可以转账~ 再去注册一个吧! ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 3 ================账户取款界面================= 请您输入取款金额: 5000 5000.0元已取走~ 请拿好您的钱和随身物品! 您账户目前的余额为: 400.0元 ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 3 ================账户取款界面================= 请您输入取款金额: 400 400.0元已取走~ 请拿好您的钱和随身物品! 您账户目前的余额为: 0.0元 ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 7 ================账户注销界面================= 您真的要销户吗?(y/n): sdgs 好的,您的账户继续保留~ ================用户操作界面================= 1.查询 2.存款 3.取款 4.转账 5.修改密码 6.退卡 7.注销账户 请您选择要办理的业务: 7 ================账户注销界面================= 您真的要销户吗?(y/n): y 您的账户已注销~ 将无法登录! ================ATM系统首页================= 1.登录账户 2.注册开户 请选择您要办理的业务: 1 当前系统无任何账户~ 请先注册开户后再登录! ================ATM系统首页================= 1.登录账户 2.注册开户 请选择您要办理的业务: