9. 综合案例-ATM系统 (1~7节知识综合练习)

ATM系统_综合大练习

  • 今天的任务是对之前所有的学习的知识, 进行一个综合性的大练习.

  • 老师说的好, 键盘敲烂

  • 这个项目我写了大量的注释给大家参考, 如果有同学是跟着我的系列学习的, 一定动手练一练.

  • 下面的代码只要按着敲是可以直接运行起来的, 我也把完整代码上传到了CSDN上面, 并已经绑定在这篇博客上, 在由于CSDN的设定, 只有电脑页面才能显示出来.

  • 由于这篇文章还在编写中, 所以就用另外一篇文章举例一下. 如下于是所示

黑马ATM系统技术选型

  1. 会使用到面向对象的思想
  • 每个账户都是一个账户对象:所以需要设计账户类Account,用于创建账户对象封装账户信息。
  • ATM同样是一个对象,需要设计ATM类,代表ATM管理系统,负责对账户的处理
  • 还需要创建一个ATM启动的测试类, 在main()方法里初始化ATM类创建ATM对象, 并调用ATM启动的方法.
  1. 合理使用集合容器
  • ATM管理类中需要提供一个容器用于存储系统全部账户对象的信息,我们选ArrayList集合。
  1. 程序流程控制
  • 需要结合分支、循环、跳转关键字等程序流程控制的知识,用来控制系统的业务流程。
  1. 使用常见的API
  • 登录信息的内容比较,数据的分析,处理等都需要常用API来解决,如使用String。

黑马ATM系统功能分析

系统架构搭建、欢迎页设计

  1. 系统架构搭建
  • 定义一个账户类Account,至少需要包含(卡号、姓名、密码、性别、余额、每次取现额度)
  • 定义一个ATM类,用来代表ATM系统,负责提供所有的业务需求,- 比如:展示ATM的系统欢迎页、开通帐户、转账……
  • 定义一个测试类Test,负责对我们开发的ATM系统进行测试。
  1. 设计ATM管理类
  • 首先设计ATM()类属性:
    • 扫描器对象Scanner: 登录的时候肯定需要输入卡号
    • 随机数对象Random: 创建卡号是需要随机生成
    • 账户属性的集合ArrayList: 用于存储账户对象
    • 登录账户对象Account: 用于存储已经登录的账户对象
    • 对象的身份loginIdentity: 由于展示时需要用到多次用户的身份, 比如说性别男就是先生, 女就是女士, 使用属性就可以全局进行使用.
    • 登陆状态loginJudge: 判断用户是在操作系统中, 还是已经退出登录了, 默认为false未登录, 登录成功就令为true, 退出登录也会令为false
package com.itheima;

import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

/**
 * @className: ATM
 * @author: LXHYouth
 * @date: 2024/3/15 9:54
 * @Version: 1.0
 * @description: ATM管理类
 */
public class ATM {
    // 创建一个扫描器对象
    Scanner scanner = new Scanner(System.in);
    // 创建一个随机数对象
    Random random = new Random();
    // 创建用户属性集合
    ArrayList<Account> accountArrayList = new ArrayList<>();
    // 创建一个用户对象, 用来存储登陆成功的用户对象, 一边全局访问
    Account loginSuccessAccount = new Account();
    // 创建一个变量存储登录用户是先生还是女士
    String loginIdentity = "";
    // 判断账号登陆状态, 默认false
    boolean loginJudge = false;
}

  1. 欢迎界面设计
  • 在ATM类中设计一个方法start(),方法里负责展示欢迎界面。
  • 并使用ATM类中的登录状态属性, 判断方法结束时, 系统将进入哪个页面.
  • 代码实现: 这是ATM类中的star()方法
/**
     * @return void
     * @MethodName star
     * @Author LXHYouth
     * @Date 2024/3/15 10:42
     * @Param []
     * @Description 黑马银行登录界面(初始化界面)
     **/
    public void star() {
        while (true) {
            // 系统开始界面初始化
            System.out.println("==欢迎进入黑马银行ATM系统==");
            System.out.println("1. 用户登录");
            System.out.println("2. 用户开户");
            System.out.print("请输入命令1、2选择对应的操作: ");
            int input = scanner.nextInt();
            switch (input) {
                case 1:
                    // 用户登录
                    login();
                    break;
                case 2:
                    // 用户开户
                    createAccount();
                    break;
                default:
                    System.out.println("您输入的操作不正确!");
                    System.out.print("请重新输入: ");
            }

            // 展示登录成功后的业务, 防止套娃,
            // 及时结束showMenu()方法, 如发现还在登录状态, 继续启动showMenu()方法.
            while (true){
                if (loginJudge) {
                    //
                    showMenu();
                }else{
                    // 如果登录状态为false就结束循环, 回到ATM开始界面
                    // 只有在用户选择退出系统, 或改密码成功, 或注销账户成功的情况下才会出现.
                    break;
                }
            }
        }
    }
  • star() 方法中的这段代码一定要弄懂, 这里是后面所有方法结束后进行判断, 是在内层业务菜单循环, 还是外层ATM欢迎界面循环.
// 展示登录成功后的业务, 防止套娃,
            // 及时结束showMenu()方法, 如发现还在登录状态, 继续启动showMenu()方法.
            while (true){
                if (loginJudge) {
                    //
                    showMenu();
                }else{
                    // 如果登录状态为false就结束循环, 回到ATM开始界面
                    // 只有在用户选择退出系统, 或改密码成功, 或注销账户成功的情况下才会出现.
                    break;
                }
            }
  1. 设计Account() 账户类
  • 注意事项: 首先需根据案例要求, 进行对账户类属性进行设定.
  • 属性有: name 名字, sex 性别, password 密码, limit 限额, idCard 卡号, balance 余额
  • 由于属性私有化, 还需要使用IDEA对属性自动生成get/set方法, 以及无参构造和全参构造方法.
  • 代码实现
package com.itheima;

/**
 * @className: Account
 * @author: LXHYouth
 * @date: 2024/3/15 9:54
 * @Version: 1.0
 * @description: 定义用户类
 *               属性有: name 名字, sex 性别, password 密码,
 *                      limit 限额, idCard 卡号, balance 余额
 *               有一个无参构造方法, 一个含参构造方法, 一个全参构造方法
 */
public class Account {
    // 属性私有化, name 名字, sex 性别, password 密码, limit 限额, idCard 卡号, balance 余额
    private String name;
    private String sex;
    private String password;
    private int limit;
    private String idCard;
    private double balance;

    // 所有属性的get/set方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    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 int getLimit() {
        return limit;
    }

    public void setLimit(int limit) {
        this.limit = limit;
    }

    public String getIdCard() {
        return idCard;
    }

    public void setIdCard(String idCard) {
        this.idCard = idCard;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    /**
     * @MethodName Account
     * @Author LXHYouth 
     * @Date 2024/3/16 17:36
     * @Param []
     * @return  
     * @Description 无参构造方法
     **/
    public Account(){
    }

    /**
     * @MethodName Account
     * @Author LXHYouth 
     * @Date 2024/3/16 17:36
     * @Param [name, sex, password, limit, idCard]
     * @return  
     * @Description 含参构造方法, name 名字, sex 性别, password 密码,
     *              limit 限额, idCard 卡号
     **/
    public Account(String name, String sex, String password, int limit, String idCard) {
        this.name = name;
        this.sex = sex;
        this.password = password;
        this.limit = limit;
        this.idCard = idCard;
    }

    /**
     * @MethodName Account
     * @Author LXHYouth 
     * @Date 2024/3/16 17:33
     * @Param [name, sex, password, limit, idCard, balance]
     * @return  
     * @Description 全参构造方法, name 名字, sex 性别, password 密码,
     *              limit 限额, idCard 卡号, balance 余额
     **/
    public Account(String name, String sex, String password, int limit, String idCard, double balance) {
        this.name = name;
        this.sex = sex;
        this.password = password;
        this.limit = limit;
        this.idCard = idCard;
        this.balance = balance;
    }
}
 
  1. 设计ATMTest() ATM测试类
  • 创建一个ATM() 对象
  • 使用对象调用Satr()方法, 展示黑马ATM银行登录操作页面
  • 代码实现
package com.itheima;

/**
 * @className: ATMTest
 * @author: LXHYouth
 * @date: 2024/3/15 9:55
 * @Version: 1.0
 * @description:    ATM的测试类
 */
public class ATMTest {
    public  static void main(String[] args){
        // 创建一个ATM对象
        ATM atm = new ATM();
        // 启动ATM
        atm.star();
    }
}
 
  1. 总结
  • ATM系统的三个类的作用是怎样的?
    • 定义了一个Account类,定义系统关心的账户信息。
    • 定义了一个ATM类,代表ATM系统,负责处理账户相关的业务需求
    • 定义了一个Test类,负责测试系统:创建ATM对象代表ATM系统并启动。

开户功能实现

  1. 用户开户功能
  • 就是新增一个账户,也就是往系统的账户集合中添加一个账户对象。
  • 需要注意的是, 要对输入的数据进行有效判断
  • 性别只能输入男或女, 输入其他提示重新输入
  • 取现额度需要进行有效性判断, 如果小于等于零, 提示用户重新输入. 根据场景就无法测试取款.
/**
     * @return void
     * @MethodName createAccount
     * @Author LXHYouth
     * @Date 2024/3/15 10:36
     * @Param []
     * @Description 实现用户开户功能
     **/
    public void createAccount() {
        System.out.println("==系统开户操作==");
        // 创建一个用户类对象
        Account creatAccount = new Account();
        System.out.print("请您输入账户用户名: ");
        creatAccount.setName(scanner.next());

        // 对输入性别进行有效性判断, 并存储
        System.out.print("请您输入您的性别: ");
        while (true) {
            String sex = scanner.next();
            if (!sex.equals("男") && !sex.equals("女")) {
                System.out.println("性别输入错误!!!");
                System.out.print("请您重新输入性别: ");
                continue;
            }
            // 判断成功后, 就存储进创建的新用户对象的性别属性中
            creatAccount.setSex(sex);
            break;
        }

        // 对密码有效性进行判断, 并保存
        System.out.print("请您输入账户密码: ");
        // 死循环实现输入错误, 进行多次输入
        while (true) {
            String pwd = scanner.next();
            System.out.print("请您输入确认密码: ");
            // 判断两次输入密码是否相同
            if (!pwd.equals(scanner.next())) {
                System.out.println("两次密码输入不一样!!!");
                System.out.print("请您重新输入密码: ");
                continue;
            }
            // 相同就存入对象属性
            creatAccount.setPassword(pwd);
            break;
        }

        // 对输入的限额数进行有效性判断, 并存储
        System.out.print("请您输入账户每次取现限额: ");
        while (true) {
            int limit = scanner.nextInt();
            if (limit <= 0) {
                System.out.print("账户限额必须大于零, 请您重新输入: ");
                continue;
            }
            creatAccount.setLimit(limit);
            break;
        }

        // 创建水机卡号, 调用创建卡号方法
        String randomIdCard = createId();
        // 用户对象变量卡号赋值
        creatAccount.setIdCard(randomIdCard);
        // 把用户对象添加到 ATM用户对象集合中去
        accountArrayList.add(creatAccount);


        // 恭喜语句
        String appellation = creatAccount.getSex().equals("男") ? "先生" : "女士";
        System.out.println("恭喜您," + creatAccount.getName() + appellation + ",您开户成功,您的卡号是:" + randomIdCard);
    }
  1. 账号的要求
  • 用户信息包含:姓名、密码、性别、每次取现额度、卡号。
  • 注意:卡号由系统生成,要求是8位的数字组成的(且卡号不能重复)。
  • 代码实现
/**
     * @return java.lang.String
     * @MethodName createId
     * @Author LXHYouth
     * @Date 2024/3/15 15:03
     * @Param []
     * @Description 用户开户成功后, 进行生成卡号
     **/
    public String createId() {
        // 实现如果生成的卡号与已有卡号相同, 就重新生成一个
        while (true) {
            // 存储卡号
            String randonIdCard = "";
            // 对每一位数字进行生成, 需进行有效性判断
            // 8位数的账号, 需要循环生成8次
            for (int i = 0; i < 8; i++) {
                // 随机生成的一位数字
                int r = random.nextInt(10);
                // 对卡号的显示场景需求, 首字位不能为零, 如果为零, 再次循环重新生成
                if (i == 0 && r == 0) {
                    // 如果为零, 需要把循环次数减一(不然就生成第二位去了), 然后跳出本次循环
                    i--;
                    continue;
                }
                // 对生成的随机数进行拼接
                randonIdCard += r;
            }

            // 判断不能生成已有的账号, 如果比对相同就跳出本次循环, 进行重新生成
            for (int i = 0; i < accountArrayList.size(); i++) {
                if (accountArrayList.get(i).getIdCard().equals(randonIdCard)) {
                    continue;
                }
            }
            // 卡号生成更改, 对卡号进行返回, 在开户的方法中接受返回值
            return randonIdCard;
        }

    }
  1. 总结
  • 开户功能的实现需要哪几步操作?
    • 定义一个开户方法:createAccount。
    • 在方法里创建一个Account账户对象,负责封装用户的账户信息(姓名、性别、密码、卡号等等)
    • 卡号需要由系统自动生成(卡号要求是8位的数字组成的,且不能重复)
    • 把账户对象存入到账户集合中去。
    • 提示开户成功!

登录功能实现

  1. 实现登录功能login()
  • 如果系统没有任何账户对象,则不允许登录。可以进行开户操作.
  • 让用户输入登录的卡号,先判断卡号是否正确,如果不正确要给出提示, 并提示用户重新输入。
  • 如果卡号正确,再让用户输入账户密码,如果密码不正- 确要给出提示,并让用户重新输入. 如果密码也正确,则给出登录成功的提示, 并进入ATM类的业务菜单 (调用showMenu()方法), 也就是之后要编写的showMenu()方法。
  • 登录成功会把 loginSuccessAccount = loginAccount 记录登录成功后的用户对象, 后面在系统未退出操作时, 会进行用到登录成功对象.
  • 把登录用户对象的状态属性loginSuccessAccount赋值为true
  • 并判断登录的用户是先生还是女士赋值给loginIdentity变量
  • 代码实现:
/**
     * @return void
     * @MethodName login
     * @Author LXHYouth
     * @Date 2024/3/15 14:30
     * @Param []
     * @Description
     **/
    public void login() {
        // 创建一个存储用户输入的账户对象(已经在账户集合 存储的账户对象中找到账号)
        Account loginAccount = new Account();
        System.out.println("==系统登录操作==");
        // 判断账号是否正确, 默认没找到
        boolean judgeIdCard = false;
        // 判断输入账户卡号是否正确
        System.out.print("请您输入登录账号: ");
        // 实现如果登录不成功, 实现多次输入
        outerLoop:      // while循环标签
        while (true) {
            String loginIdCard = scanner.next();
            //  查找到账户卡号: 直接跳出外循环
            for (int i = 0; i < accountArrayList.size(); i++) {
                if (loginIdCard.equals(accountArrayList.get(i).getIdCard())) {
                    loginAccount = accountArrayList.get(i);
                    judgeIdCard = true;
                    // while循环带上标签, 可以使用break 标签, 退出带标签的循环
                    break outerLoop;
                }
            }
            if (!judgeIdCard) {
                // 提示系统中没有找到卡号
                System.out.println("系统中不存在该账户卡号~~~");
                System.out.print("请您重新输入卡号: ");
                continue;
            }
            break;
        }

        System.out.print("请您输入登陆密码: ");
        // 死循环实现 密码输入错误, 可以继续多次输入
        while (true) {
            String pwd = scanner.next();
            if (!pwd.equals(loginAccount.getPassword())) {
                System.out.print("您输入的密码有误~~~" +
                        "\n请您重新输入密码: ");
                continue;
            }
            break;
        }
        // 对登录成功用户进行赋值
        loginSuccessAccount = loginAccount;
        // 对登录成功用户身份进行判断后赋值
        loginIdentity = loginAccount.getSex().equals("男") ? "先生" : "女士";
        loginJudge = true;

        // 欢迎语句
        System.out.println("恭喜您, " + loginSuccessAccount.getName()
                + loginIdentity + ", 您已经进入系统,您的卡号是:" + loginSuccessAccount.getIdCard());

    }
  1. 总结
  • 登录功能如何实现?
    • 设计一个登录方法:login,负责完成用户的登录。
    • 方法里:如果系统无任何账户对象,直接结束登录操作。
    • 有账户对象,则让用户输入卡号,根据卡号去账户集合中查询账户对象。
    • 如果没有找到账户对象,说明登录卡号不存在,提示继续输入卡号。
    • 如果找到了账户对象,说明卡号存在,继续输入密码。
    • 如果密码不正确,提示继续输入密码。
    • 如果密码也正确,则登陆成功,并给出相应的提示。

操作页展示

  • 用户登录成功后,需要进入用户操作页(调用showMenu()方法进入业务菜单)。

  • 这里使用的是switch分支语句进行判断 (已经知道有七个分支)

  • 注意: 每进入一个分支都需要写break; 不然会出现穿透现象.

  • 在switch分支语句外面使用了一个while死循, 可以防止用户输入错误, 可以进行重复输入, 如果输入正确执行完分支语句一定要有一个break语句跳出外面的while死循环.

  • 代码实现

/**
     * @return void
     * @MethodName showMenu
     * @Author LXHYouth
     * @Date 2024/3/15 17:14
     * @Param []
     * @Description 展示登录成功后可以办理的业务界面
     **/
    public void showMenu() {
        System.out.println("==" + loginSuccessAccount.getName() + loginIdentity + ",您可以办理以下业务==");
        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("请选择: ");
        while (true) {
            int select = scanner.nextInt();
            switch (select) {
                case 1:
                    // 查询账号方法
                    checkAccount();
                    break;
                case 2:
                    // 存款
                    deposit();
                    break;
                case 3:
                    // 取款
                    withdrawMoney();
                    break;
                case 4:
                    // 转账
                    transfer();
                    break;
                case 5:
                    // 修改密码
                    changePassword();
                    break;
                case 6:
                    // 退出
                    quit();
                    System.out.println("账号安全退出成功!!!");
                    break;
                case 7:
                    // 注销账户
                    cancelAccount();
                    break;
                default:
                    System.out.print("对不起输入有误, 请您重新输入: ");
            }
            break;
        }

    }

查询账户、

  • 查询就是直接展示当前登录成功的用户的账户信息。
  • 通过之前包从的登录成功账户对象, 调用其向的属性进行打印.
  • 代码实现
/**
     * @MethodName checkAccount
     * @Author LXHYouth 
     * @Date 2024/3/16 9:24
     * @Param []
     * @return void 
     * @Description showMenu方法中 case1调用该方法, 用于展示账户的基本信息(查询账户信息)
     **/
    public void checkAccount(){
        // 查询会展示账号, 性别, 用户名, 限额
        System.out.println("尊贵的"+loginSuccessAccount.getName()
                +loginIdentity+"您好, \n您的信息展示如下: ");
        System.out.println("卡号: "+loginSuccessAccount.getIdCard());
        System.out.println("用户名: "+loginSuccessAccount.getName());
        System.out.println("性别: "+loginSuccessAccount.getSex());
        System.out.println("余额: "+loginSuccessAccount.getBalance());
        System.out.println("限额: "+loginSuccessAccount.getLimit());
        System.out.print("请您随便输入, 然后点击回车返回业务菜单: ");
        scanner.next();
    }

存款

  • 就是用户为自己的账户存钱,存钱后更新账户的余额即可。
  • 注意: 存钱需要对用户输入的金额进行有效性判断, 如果存入金额小于等于零, 就提示用户金额有误, 并让用户重新输入. 如果输入金额没有问题, 调用用户对象的set方法进行金额的修改.
  • 并显示存款成功的信息, 和打印出现在的余额.
  • 代码实现
/**
     * @MethodName deposit
     * @Author LXHYouth 
     * @Date 2024/3/16 10:05
     * @Param []
     * @return void 
     * @Description showMenu方法 case 2 调用, 本方法进行存款操作.
     **/
    public void deposit(){
        System.out.println("========存款操作界面========");
        // 存储存款金额
        double depositPrice=0;
        // 提示用户输入存款金额
        System.out.print("请您输入存款金额: ");
        // 实现金额输入错误, 可以多次重新输入
        while(true){
            depositPrice= scanner.nextDouble();
            // 对输入金额有效性判断, 金额不能小于等于零
            if (depositPrice<=0){
                System.out.print("存款金额小于等于零, 请您重新输入: ");
                continue;
            }
            // 满足要求退出循环
            break;
        }
        // 把存入的金额, 加到余额中去
        double sumPrice= loginSuccessAccount.getBalance()+depositPrice;
        loginSuccessAccount.setBalance(sumPrice);
        System.out.println("尊贵的"+loginSuccessAccount.getName()+loginIdentity+"您的存款成功!!!");
        System.out.println("账户余额为: "+loginSuccessAccount.getBalance());
        // 控制换行
        System.out.println();

    }

取款功能实现

  • 用户取款功能就是从自己的账户中取钱,取钱的要求:
  • 首先需要先让用户输入取款金额
  • 需要判断取款金额是否超过了当次限额,以及余额是否足够。
  • 注意: 这里也要对用户输入金额进行有效性判断, 不能小于等于零, 不能大于余额.
  • 代码实现
/**
     * @MethodName withdrawMoney
     * @Author LXHYouth 
     * @Date 2024/3/16 11:12
     * @Param []
     * @return void 
     * @Description     showMenu方法 case 3 调用, 本方法进行取钱操作.
     **/
    public void withdrawMoney(){
        System.out.println("========取款操作界面=========");
        // 提示用户输入取钱金额
        System.out.print("请您输入取款金额: ");
        while(true){
            // 存储键盘输入取款金额
            double inputPrice=scanner.nextDouble();
            // 对金额进行有效性判断
            // 金额小于等于零, 提示用户重新输入
            if (inputPrice<=0){
                System.out.print("您输入的取款金额小于等于零, 请重新输入: ");
                continue;
            }
            // 金额超过限额, 提示用户重新输入
            if (inputPrice>loginSuccessAccount.getLimit()){
                System.out.print("您取款的金额超过限额!!!\n请您重新输入取款金额: ");
                continue;
            }
            // 取款金额大于余额, 提示用户重新输入
            if (inputPrice>loginSuccessAccount.getBalance()){
                System.out.println("您的余额不足!!!\n请重新输入取款金额: ");
                continue;
            }
            double endPrice=loginSuccessAccount.getBalance()-inputPrice;
            loginSuccessAccount.setBalance(endPrice);
            System.out.println("尊贵的"+loginSuccessAccount.getName()
                    +loginIdentity+", 恭喜您取款成功!!! \n您的余额为:  "
                    +loginSuccessAccount.getBalance());
            break;
        }
    }

转账功能实现

  • 首先需要用户输入需要转账用户的卡号.
  • 然后对输入卡号进行比对, 对账户对象集合中的对象进行遍历, 每遍历一个用户对象, 就调出卡号属性, 进行比对, 如果账户不存在就提示用户重新输入, 如果存在就提示用户验证对方姓氏.
  • 验证不成功的话, 就提示用户重更新输入, 验证成功就开始下一步.
  • 用户输入转账金额后, 需要对用户输入的金额进行有效性判断, 不能小于等于零, 不能大于转账的限额, 也不能大于余额.
  • 如果金额输入正确, 就对调用登录用户对象set方法设置转后的金额, 对方转账用户对象的金额属性就加上转账的金额
  • 然后打印出转账金额和账户余额
  • 代码实现
/**
     * @MethodName transfer
     * @Author LXHYouth 
     * @Date 2024/3/17 21:02
     * @Param []
     * @return void 
     * @Description     showMenu方法 case 4 调用, 本方法进行转账操作.
     **/
    public void transfer(){
        // 创建一个Account对象, 用来存储转账用户对象
        Account transferAccount=null;
        System.out.println("=========转账操作页面========");
        // 提示用户输入转账账号
        System.out.print("请输入对方账户: ");
        outerLoop:
        while(true){
            String inputTransferNumber=scanner.next();
            if (loginSuccessAccount.getIdCard().equals(inputTransferNumber)){
                // 判断是否为自己用户
                System.out.print("不能给自己转账, 请重新输入账户: ");
                continue;
            }

            // 循环判断输入的转账账户存储存在
            for (int i = 0; i < accountArrayList.size(); i++) {
                // 存在的情况下, 就直接跳出最外层循环
                if(accountArrayList.get(i).getIdCard().equals(inputTransferNumber)){
                    transferAccount=accountArrayList.get(i);
                    break outerLoop;
                }
                // 当查到账户对象集合中的最后一个还是没有找到, 就说明不存在
                if (i==accountArrayList.size()-1){
                    System.out.print("您输入的账户不存在, 请重新输入: ");
                }
            }
            break;
        }

        // 获取转账账号的用户名, 对用户名进行加密处理
        String tempName="";
        // 判断用户名长度, 分别进行处理
        if (transferAccount.getName().length()>1){
            tempName="*"+transferAccount.getName().substring(1);
        }else {
            tempName="*";
        }
        // 判断转账用户是男是女, 然后使用的称呼
        String identity=transferAccount.getSex().equals("男")?"先生":"女士";
        System.out.println("您当前要为"+tempName+identity+"转账");
        // 并要求用户验证账号姓氏
        System.out.print("请您输入对方用户的姓氏, 进行验证: ");
        while (true){
            // 获得姓氏
            String lastName=scanner.next();
            if (!lastName.equals(String.valueOf(transferAccount.getName().charAt(0)))){
                System.out.print("您输入的姓氏不正确, 请您重新输入: ");
                continue;
            }
            break;
        }

        // 存储转账金额
        double inputPrice=0;
        // 提示用户输入金额
        System.out.print("请您输入转账金额: ");
        while(true){
            inputPrice= scanner.nextDouble();
            // 对金额进行有效性判断
            // 金额小于等于零, 提示用户重新输入
            if (inputPrice<=0){
                System.out.print("您输入的取款金额小于等于零, 请重新输入: ");
                continue;
            }
            if (inputPrice>loginSuccessAccount.getLimit()){
                System.out.print("转账金额超过限额, 请您重新输入: ");
                continue;
            }
            if (inputPrice>loginSuccessAccount.getBalance()){
                System.out.print("账户余额不足, 请您重新输入: ");
                continue;
            }


            break;
        }
        // 登录账户的最后账户余额, 需要使用转账前余额减去转账余额
        double myEndPrice= loginSuccessAccount.getBalance()-inputPrice;
        loginSuccessAccount.setBalance(myEndPrice);
        // 转入账户最后余额为, 未转入前金额加上转入余额
        double transferEndPrice=transferAccount.getBalance()+inputPrice;
        transferAccount.setBalance(transferEndPrice);
        // 提示用户转账成功
        System.out.println("尊贵的"+loginSuccessAccount.getName()+loginIdentity+"您的进行的转账已成功!!!");
        System.out.println("您的转账金额为: "+inputPrice+", 账户余为: "+loginSuccessAccount.getBalance());
        System.out.println("请您认真查看如上信息, 如有问题请尽快联系我行工作人员!!!");
    }

用户密码修改

  • 密码修改就是要更改账户的登录密码
  • 修改密码的要求:
    • 进入密码修改页面先判断用户是否确定修改密码, 输入 n 就直接结束修改密码方法, 然后对登录状态进行判断, 输入 y 的话就进行下一步.
    • 先认证用户当前的密码, 如果输入错误只能让用户输入三次, 错误三次后就直接结束修改密码的方法, 然后代码就是跳回ATM的star() 方法内, 由于没有进行退出操作, 所以对登录状态初始为false, 所以在star()方法中, 进行登录状态判断是为true, 那么还是会调用showMenu方法, 进入业务菜单.
    • 如果密码认证通过后,需要让用户输入2次新密码, 如果两次不一样就提示用户重新输入, 如果两次密码一样,则更新账户密码,就调用quit()方法, 对登录信息进行清楚, 如登录的用户对象信息为null, 用户身份信息为null, 登录状态信息为false 等, 清除成功后, 就会返回到star()方法内, 然后对登录状态进行判断, 发现为false, 就结束本次系统内循环, 进入ATM欢迎界面。
  • 重新登陆原来的密码已经显示密码错误, 使用新密码登录成功.
  • 代码实现
/**
     * @MethodName changePassword
     * @Author LXHYouth 
     * @Date 2024/3/16 8:52
     * @Param []
     * @return void 
     * @Description     showMenu方法 case5调用
     **/
    public void changePassword() {
        System.out.println("==欢迎您进入黑马银行密码修改界面========");
        // 存储判断是否修改密码
        String whetherChange = "";
        System.out.print("是否确定修改密码(y/n):");
        // 存储键盘输入的y or n
        whetherChange = scanner.next();
        // 进行判断是否修改密码
        if (whetherChange.equals("n")) {
            // 当输入n  时, 直接展示业务菜单
             return;
        }

        // 没有进if循环, 说明输入 y 确定修改密码
        // 创建一个记录密码输入次数的计数器
        int inputPwdCount=0;
        System.out.print("请您输入当前账户的密码:");
        while(true){
            // 当计数器等于3 的时候, 直接提示输入密码错误三次, 然后展现业务菜单
            if (inputPwdCount==3){
                System.out.println("您输入密码错误达到三次, 禁止输入!!!");
                return;
            }
            // 创建一个变量, 存储输入的密码
            String inputPassword = scanner.next();
            // 每输入一次密码计数加一
            inputPwdCount++;
            if (!inputPassword.equals(loginSuccessAccount.getPassword())){
                System.out.print("当前账户密码不正确!!! 还有"+(3-inputPwdCount)+"次机会 \n请您重新输入当前账户密码: ");
                continue;
            }
            // 密码验证正确, 直接结束死循环
            break;
        }

        // 提示用户输入新密码
        System.out.print("请您输入新的密码: ");
        while(true){
            String newPassword=scanner.next();
            System.out.print("请您确认新密码: ");
            if(!newPassword.equals(scanner.next())){
                System.out.print("两次输入的密码不一致, \n请您重新输入: ");
                continue;
            }
            // 两次密码输入相同, 就把新密码存入对象密码成员变量中
            loginSuccessAccount.setPassword(newPassword);
            System.out.println("密码修改成功!!!");
            break;
        }
        // 修改密码后进行重新登录, 调用退出方法
        quit();
        System.out.println("请您重新登入!!!");
    }

退出账户

  • 退出账户就是回到欢迎页面。
  • 上面的修改密码成功后就回调用quit()方法, 原理上面已经讲解过来就不再复述了, 直接上代码吧.
  • 代码实现
/**
     * @return void
     * @MethodName quit
     * @Author LXHYouth
     * @Date 2024/3/15 17:18
     * @Param []
     * @Description showMenu方法中case6调用 退出需要把用户对象清空, 登录身份清空, 登录状态需要为false
     **/
    public void quit() {
        // 清空登录的账户对象信息
        loginSuccessAccount = null;
        // 令用户身份为空
        loginIdentity = "";
        // 登录状态为false
        loginJudge = false;
        System.out.print("登录信息清除成功, ");
    }

销户功能实现

  • 销户操作的基本需求
    • 销户就是从系统中删除当前账户,销户的要求:
    • 首先要询问用户是否确定要销户,如果不确定,结束掉销户方法cancelAccount(), 回到操作界面。
    • 如果确定,要判断用户的账户中是否有钱,有则不允许销户,并回到操作界面。
    • 如果没钱,则完成销户,调用quit()方法, 并回到欢迎页。
    • 然后再使用刚刚销户的账号进行登录, 发现系统提示型账号不存在, 说明销户成功.
    • 代码实现
/**
     * @MethodName cancelAccount
     * @Author LXHYouth 
     * @Date 2024/3/16 9:49
     * @Param []
     * @return void 
     * @Description     showMenu方法 case7调用, 方法执行销户操作
     **/
    public void cancelAccount(){
        //  创建一个销户判断变量, 默认为空
        String cancelAccountJudge="";
        // 提示用户进入注销账号页面
        System.out.println("欢迎来到账户注销页面!");
        System.out.print("您是否确定要销户? y/n : ");
        // 存储键盘输入的选择y/n
        cancelAccountJudge=scanner.next();
        // 如果取消的, 直接结束方法
        if(cancelAccountJudge.equals("n")){
            System.out.println(" 取消成功, 将返回业务菜单!!!");
            return;
        }
        // 运行到这说明用户输入y, 下面判断用户账号是否还有余额
        if (loginSuccessAccount.getBalance()>0){
            System.out.println("尊贵的"+loginSuccessAccount.getName()+loginIdentity
                    +"您的账户余额为: "+loginSuccessAccount.getBalance()
                    +"\n无法进行注销操作, 请您处理存款后再进行销户操作!!!");
            return;
        }
        // 账户金额为零, 就进行删除集合中的用户对象, 然后提示注销成功
        if (accountArrayList.remove(loginSuccessAccount)){
            System.out.println("账号注销成功, 欢迎您下次光临我行!!!");
        }
        // 调用退出系统, 清空登录的账号信息
        quit();
    }

  • 到此教程就结束了.
  • 转载: 请附上本文链接.
  • 如果文章对你有帮助, 可以点赞收藏一下, 以防下次需要可以快速找到.

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Fritzing 简单使用

文章目录 1 Fritzing 资源2 Fritzing 简单使用3 添加自已的元器件3.1 面包板3.1.1 新建面包板 svg 文件3.1.2 新建面包板 3.2 原理图3.3 PCB3.4 图标3.5 使用 1 Fritzing 资源 1&#xff09;官网&#xff1a; 开源的电子设计和原型平台&#xff1a;https://fritzing.org/免费开…

机试:砍树修路

问题描述 代码示例&#xff1a; //一坐标轴表示某道路&#xff0c;从0开始 到L&#xff0c;整数位置上都种有一颗树。现在该路修建地铁&#xff0c;要砍掉铁路线路上的树木。例如&#xff1a;L等于10&#xff0c;铺设4条铁路&#xff0c;坐标是1到2,2到3,2到8&#xff0c;3到…

【SpringBoot】解决数据库时间和返回时间格式不一致的问题

先看问题: 类中的属性中有Date类型的属性 数据库表中的数据: 可以看到也没问题 但是在返回实体类对象时,数据类型是这样的: 虽然数据是成功返回了,但这显然不是我们想要的结果.也不符合我们的日常使用习惯. 这个问题虽然前端,后端都能处理,但最好还是后端来进行处理.前端主…

openEuler学习总结1(仅供学习参考)

华为的openEuler内核是源于Linux。 openEuler操作系统安装流程 第一步&#xff1a;开启虚拟化 第二步&#xff1a;安装一个虚拟化软件virtualbox 第三步&#xff1a;镜像 第四步&#xff1a;配置 设置虚拟机所在的目录 把网卡类型选择成桥接网卡 挂载镜像 设置完成&#xff0…

玩转键盘鼠标,自动化你的电脑操作 —— 定时执行专家

简介 “定时执行专家”是一款功能强大的定时任务执行软件&#xff0c;除了支持常见的定时关机、重启、执行程序等功能外&#xff0c;还拥有模拟键盘按键和模拟鼠标操作功能&#xff0c;可以让你轻松实现各种自动化操作。 模拟键盘按键功能可以模拟用户的键盘输入&#xff0c;让…

BufferedOutputStream类讲解

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java IO相关知识点了&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好…

GEE错误——Line 12: xxx.size is not a function(计算列表长度出现错误)

简介 这里我们再计算研究区面积的时候出现了一个错误,这里的问题是Line 12: points8.size is not a function 主要问题是xxx不是一个数组或者对象,无法调用size方法。这里的问题是我们要获取这个对象的时候出现了问题,也就说你给函数传输的并不是一个对象,而不知道是什么…

基于Springboot+Vue+Sercurity实现的大学生健康管理平台

1.项目介绍 大学生健康档案管理系统&#xff0c;通过电子健康档案管理系统这个平台&#xff0c;可以实现人员健康情况的信息化、网络化、系统化、规范化管理&#xff0c;从繁杂的数据查询和统计中解脱出来&#xff0c;更好的掌握人员健康状况。系统的主要功能包括&#xff1a;…

7.JavaWebHTML:构建数字世界的语言和结构

目录 导语&#xff1a; 第一部分&#xff1a;Web概念与作用 1.1 Web的定义 1.2 Web的作用 1.3 JavaWeb 第二部分&#xff1a;HTML概念与内容 2.1 HTML的定义 2.2 HTML的内容 第三部分&#xff1a;HTML的作用 3.1 HTML的作用 3.2 HTML在现代Web开发中的角色 …

2024.3.15

1.单向循环链表 代码&#xff1a; #include"loop.h" //创建单向循环链表 loop_p create_loop_list() {loop_p H (loop_p)malloc(sizeof(loop));if(HNULL){printf("空间申请失败\n");return NULL;}H->len0;H->nextH;return H; } //创建节点 loop_p…

【晴问算法】入门篇—贪心算法—整数配对

题目描述 有两个正整数集合S、T&#xff0c;其中S中有n个正整数&#xff0c;T中有m个正整数。定义一次配对操作为&#xff1a;从两个集合中各取出一个数a和b&#xff0c;满足a∈S、b∈T、a≤b&#xff0c;配对的数不能再放回集合。问最多可以进行多少次这样的配对操作。 输入描…

C语言数据类型 ---变量的定义

目录 关键字&#xff08;Keywords&#xff09; 标识符&#xff08;Identifiers&#xff09; *命名规则 *常量&#xff08;Constant&#xff09; *变量&#xff08;Variable&#xff09; 变量的定义 小结 变量的4个基本属性 程序设计语言的基本构成要素 自然语言程序设…

【Godot4.0】自定义A*寻路拓展类TileMapAStar2D及其使用

概述 Godot提供的AStar2D和AStarGrid2D基本可以解决所有2D的A*寻路问题&#xff1a; 前者提供了基础的A*寻路支持&#xff0c;但是需要手动处理很多内容后者针对基于方形图块的A*寻路&#xff0c;进行了很多自动化的工作&#xff0c;用起来十分简便。但是不使用于六边形、iso…

人人站CMS后台登不进去解决方案(已解决)

公司有一个网站使用的是人人站CMS&#xff0c;最近发现后台登录不进去&#xff0c;有以下报错 发生以下错误: file get contents(http://www.rrzcms.com/Public/cms/config/config.ison): failed to open stream: HTTP reguest failed! 请求的URL导致内部服务器错误。 如果您反…

3.4 bp,si,di寄存器,寻址方式,寄存器总结

汇编语言 1. [bxidata] 我们可以用[bx]来指明一个内存单元我们也可以用[bxidata]来表示一个内存单元&#xff0c;它的偏移地址为bx中的数值加上idata mount c d:masm c: debug r d 2000:1000 e 2000:1000 12 34 56 78 a mov ax,2000 mov ds,ax mov bx,1000 mov ax,[bx] mov c…

如何创建用户流(User Flow):分步指南

原文作者&#xff1a;Camren Browne&#xff0c;CareerFoundry 翻译&#xff1a;数字营销工兵 (sources: 图片来源于网络&#xff09; 用户流(User Flow)是当今用户体验行业中最有用但被误解的工具之一。资深设计师经常避开它们&#xff0c;而初级设计师则很难抓住它们。 事…

代码算法训练营day7 | 454.四数相加II、383. 赎金信、15. 三数之和、18. 四数之和

day7: 剩下的两题&#xff1a; 15. 三数之和18. 四数之和 15. 三数之和 题目链接 状态&#xff1a; 文档&#xff1a;programmercarl.com 注意&#xff1a; 这和第一题中的四数相加Ⅱ很像&#xff0c;如果用哈希算法的思路就是&#xff1a; 两层for循环就可以确定 a 和b 的数值…

C++面向对象程序设计 - 创建学生类

在20世纪80年代提出了面向对象的程序设计&#xff08;Object oriented programming, OOP&#xff09;思想&#xff0c;在此形势下&#xff0c;C由AT&TBell&#xff08;贝尔&#xff09;实验室于20世纪80年代初在C语言的基础上开发成功&#xff0c;C保留了C语言原有的所有优…

(C语言)整数在内存中的存储与大小端

1. 整数在内存中的存储 整数的2进制表示方法有三种 &#xff0c;即 原码、反码和补码 有符号类型数据三种表示方法均有符号位和数值位两部分 &#xff0c;符号位都是用0表示“正” &#xff0c;用1表示“负” &#xff0c;最高位的一位是被当做符号位 &#xff0c;剩余的都是…

智慧公厕建设的主要目标是什么?

随着城市化进程的不断推进&#xff0c;公共厕所作为城市基础设施的重要组成部分&#xff0c;也变得越来越重要。为了提升公共厕所的管理水平、提供更好的服务质量&#xff0c;智慧公厕应运而生。智慧公厕的建设旨在通过信息化手段实现公共厕所的全面感知监测&#xff0c;实现公…