Java银行账户管理系统实验总结





1. 代码编写过程说明

  • chapter4:使用基本面向对象思想实现简单功能,引入Account类;
  • chapter5: 在类中增添了静态属性与静态方法;
  • chapter6:增添字符串作为域变量,main方法中使用对象数组存储账户,引入Data类管理时间,与Account进行组合;
  • chapter7:使用了类的继承与派生,优化了类结构,父类为Account,子类为CreditAccount,引入Accumulate类,与Account类及其子类进行组合;
  • chapter8:运用了多态属性,将Account设为抽象类,CreditAccount为其实现类;
  • chapter9:使用ArrayList作为容器。
    类结构


2. 实现中发现的问题

C++中cosnt与Java中final的比较:
  • C++中:

    • const用于基本数据类型前修饰常量,其值不能更改;
    • const A *p = &a 表示其指向对象的内容不改变;
    • A cosnt *p = &a 表示其指向不能改变,即指针的值不能改变;
    • const修饰函数表示该函数为常成员函数,只能读取类中数据成员,不能修改;
    • public methodA(const classA *p){ }防止参数指针指向被修改;
    • public methodA(const int a){ }在程序中不能修改a的值。
  • Java中:

    • final用于基本数据类型前,为常量标识符;
    • final用于对象引用前,修饰常引用,其绑定对象不能改变为其他对象;
    • final用于类前修饰最终类,表示其不能有派生类;
    • final用于方法前修饰最终方法,表示其方法不能被其派生类覆盖,当可以在本类中重载;
    • final用在参数列表中不能表示其值不能修改的语义,要想达到此目的则在方法内部加入限制性操作语句。

C++中 虚函数与纯虚函数的区别 以及在Java中对应的思想与实现:
  • C++中,虚函数是实现多态的重要工具,对应java中的普通函数。
#include<iostream>
using namespace std;
class A
{
    public:
        void print()
        {		cout<<"This is A"<<endl;		}
};
 
class B : public A
{
    public:
        void print()
        {		cout<<"This is B"<<endl;		}
};
 int mian(){
    A a;
    B b;
    A *p1 = &a;
    A *p2 = &b;
    p1->print();
    p2->print();
    return 0;
 }

输出结果都为“This is A”

#include<iostream>
using namespace std;
class A
{
    public:
        virtual void print(){cout<<"This is A"<<endl;}
};
class B : public A
{
    public:
    void print(){cout<<"This is B"<<endl;}
};

int main(){
    A a;
    B b;
    A *p1 = &a;
    A *p2 = &b;
    p1->print();
    p2->print();
    return 0;
}

分别输出“This is A”和“This is B”

通过使用Virtual定义虚函数,使基类的对象指针可以通过统一的接口访问到基类及其派生类的同名函数。

class AClass {
    public void Print() {
        System.out.println("this is A");
    }
}

class BClass extends AClass {
    public void Print() {
        System.out.println("this is B");
    }
}

public class TestA {
    public static void main(String[] args) {
        AClass a = new AClass();
        BClass b = new BClass();
        AClass pa = a;
        AClass pb = b;
        a.Print();
        b.Print();
    }
}

分别输出“this is A”和“this is B”

在Java中,直接使用普通方法和基类引用即可访问到父类和其派生类的同名方法。

  • C++中的纯虚函数也是其实现多态的重要方式,对应着Java中的抽象方法。

C++中纯虚函数是只有声名没有实现的方法,其实现在其子类中。含有纯虚函数的类为抽象类

virtual void deposit(const Date &date, double amount, const std::string &desc) = 0;
	//取出现金,date为日期,amount为金额,desc为款项说明
	virtual void withdraw(const Date &date, double amount, const std::string &desc) = 0;
	//结算(计算利息、年费等),每月结算一次,date为结算日期
	virtual void settle(const Date &date) = 0;
	//显示账户信息

以上在Java中对应为:

	abstract public void deposit(Data data,double amount,String desc);
    abstract public void withdraw(Data data,double amount,String desc);
    abstract public void settle(Data data);

Java中,抽象方法只有声名没有实现,用关键词abstract修饰,含有抽象方法的类为抽象类,也用abstract修饰。其子类必须实现其方法。


3.代码展示

工程结构总预览
main方法

package chapter9;
import java.util.ArrayList;
import java.util.Scanner;

public class BankManageSystem {
    public static void main(String[] args) {
        Data data = new Data(2008,11,1);

        ArrayList<Account> account = new ArrayList<>();

        System.out.println("MENU\n"+
                "(a)add account \n"+
                "(d)deposit \n" +
                "(w)withdraw \n" +
                "(s)show \n" +
                "(c)change day \n" +
                "(n)next month \n" +
                "(e)exit");

        char cmd;
        Scanner scanner = new Scanner(System.in);

        do {
            data.show();
            System.out.print("\tTotal: "+Account.getTotal()+"\tcommand> ");

            char type;
            int index,day;
            double amount,credit,rate,fee;
            String decs,id;

            cmd = scanner.next().charAt(0);
            switch (cmd) {
                case 'a':
                    Scanner sc = new Scanner(System.in);
                    System.out.print("type> ");
                    type = scanner.next().charAt(0);
                    System.out.println(type);
                    System.out.print("ID> ");
                    id = sc.nextLine();
                    System.out.print("*"+id+"* ");
                    if(type == 's') {
                        System.out.print("rate> ");
                        rate = scanner.nextDouble();
                        account.add(new SavingAccount(data,id,rate));
                    } else {
                        System.out.print("credit rate fee> ");
                        credit = scanner.nextDouble();
                        rate = scanner.nextDouble();
                        fee = scanner.nextDouble();
                        account.add(new CreditAccount(data,id,credit,rate,fee));
                    }
                    break;

                case 'd':
                    System.out.print("index> ");
                    index = scanner.nextInt();
                    System.out.print("amount> ");
                    amount = scanner.nextInt();
                    System.out.print("desc> ");
                    decs = scanner.nextLine();
                    account.get(index).deposit(data,amount,decs);
                    break;

                case 'w':
                    System.out.print("index amount> ");
                    index = scanner.nextInt();
                    amount = scanner.nextInt();
                    System.out.print("desc> ");
                    decs = scanner.nextLine();
                    account.get(index).withdraw(data,amount,decs);
                    break;

                case 's':
                    for(int i = 0; i<account.size(); i++) {
                        System.out.print("["+i+"]");
                        account.get(i).show();
                    }
                    break;

                case 'c':
                    day = scanner.nextInt();
                    if(day > data.getDay()) {
                        System.out.print("You cannot specify a previous day");
                    } else if(day > data.getMaxDay()) {
                        System.out.print("Invalid day");
                    } else {
                        data = new Data(data.getYear(),data.getMonth(),day);
                    }
                    break;

                case 'n':
                    if(data.getMonth() == 12) {
                        data = new Data(data.getYear()+1,1,1);
                    } else {
                        data = new Data(data.getYear(), data.getMonth()+1, 1 );
                    }
                    for (Account value : account) {
                        value.settle(data);
                    }
                    break;

                default:
                    break;
            }

        } while (cmd != 'e');
    }
}

主体类

----------------------ACCOUNT----------------------------
abstract public class Account {
    private String id;
    private double balance;
    static private double total = 0;

    protected Account(Data data,String id) {
        this.id = id;
        balance = 0;
        data.show();
        System.out.println("\t#"+id+" created");
    }

    protected void record(Data data,double amount,String desc) {
        amount = Math.floor(amount*100 + 0.5)/100;
        balance += amount;
        data.show();
        System.out.println("\t#"+id+"\t"+amount+"\t"+balance+"\t"+desc);
    }

    protected void error(String msg) {
        System.out.println("ERROR(#"+id+"): "+msg);
    }

    public String getId() {
        return id;
    }

    public double getBalance() {
        return balance;
    }

    public static double getTotal() {
        return total;
    }

    public void show(){
        System.out.println(id+"\tBalance: "+balance);
    }

    abstract public void deposit(Data data,double amount,String desc);
    abstract public void withdraw(Data data,double amount,String desc);
    abstract public void settle(Data data);
}

---------------------CREDITACCOUNT-----------------------------

public class CreditAccount extends Account{
    private Accumulator acc;
    private double credit;
    private double rate;
    private double fee;

    public CreditAccount(Data data,String id,double credit,double rate,double fee) {
        super(data,id);
        this.credit = credit;
        this.rate = rate;
        this.fee = fee;
        acc = new Accumulator(data,0);
    }

    private double getDebt() {
        double balance = getBalance();
        return (balance<0 ? balance : 0);
    }

    public double getCredit() {
        return credit;
    }

    public double getRate() {
        return rate;
    }

    public double getFee() {
        return fee;
    }

    public double getAvailableCredit() {
        if(getBalance() < 0) {
            return credit + getBalance();
        } else {
            return credit;
        }
    }

    public void deposit(Data data,double amount,String desc) {
        record(data,amount,desc);
        acc.change(data,getDebt());
    }

    public void withdraw(Data data,double amount,String desc) {
        if(amount - getBalance() > credit) {
            error("not enough credit");
        } else {
            record(data,-amount,desc);
            acc.change(data,getDebt());
        }
    }

    public void settle(Data data) {
        double interest = acc.getSum(data)*rate;
        if(interest != 0) {
            record(data,interest,"interest");
        }
        if(data.getMonth() == 1) {
            record(data,-fee,"annual fee");
        }
        acc.reset(data,getDebt());
    }

    public void show() {
        super.show();
        System.out.println("\tAvailable credit:"+getAvailableCredit());
    }

}

----------------------SAVINGACCOUNT----------------------------

public class SavingAccount extends Account {
    private Accumulator acc;
    private double rate;

    public SavingAccount(Data data,String id,double rate) {
        super(data, id);
        this.rate = rate;
        acc = new Accumulator(data,0);
    }

    public double getRate(){
        return rate;
    }

    public void deposit(Data data,double amount,String desc) {
        record(data,amount,desc);
        acc.change(data,getBalance());
    }

    public void withdraw(Data data,double amount,String desc) {
        if (amount > getBalance()) {
            error("not enough money");
        } else {
            record(data,-amount,desc);
            acc.change(data,getBalance());
        }

    }

    public void settle(Data data) {
        if(data.getMonth() == 1) {
            double interest = (acc.getSum(data)*rate)/
                    (data.minus(new Data(data.getYear()-1,1,1)));
            if(interest != 0) {
                record(data,interest,"interest");
            }
            acc.reset(data,getBalance());
        }
    }
}

封装的其他类

----------------------DATA-------------------------
public class Data {
    private int year;
    private int month;
    private int day;
    private int totalDays = 0;
    final private int[] DAYS_BEFORE_MONTH;

    Data(int year, int month, int day){
        this.year = year;
        this.month = month;
        this.day = day;

        DAYS_BEFORE_MONTH = new int[] { 0, 31, 59, 90, 120, 151,
                181, 212, 243, 273, 304, 334, 365 };

        if(day <= 0 || day > getMaxDay()) {
            System.out.print("Invalid data:");
            show();
            System.exit(1);
        }


        int years = year - 1;
        totalDays = year*365 + years/4 - years/100 + years/400
                + DAYS_BEFORE_MONTH[month - 1] + day;
        if (isLeapYear() && month > 2){
            totalDays++;
        }
    }

    /**
     * 判断是否为润年
     * @return 是否为润年
     */
    private boolean isLeapYear(){
        return year%4==0 && year%100!=0 || year%400==0 ;
    }

    public int getYear(){
        return year;
    }
    public int getDay() {
        return day;
    }
    public int getMonth() {
        return month;
    }

    public int getMaxDay(){
        if( isLeapYear() && month==2 ){
            return 29;
        } else {
            return DAYS_BEFORE_MONTH[month] - DAYS_BEFORE_MONTH[month-1];
        }
    }

    /**
     * 计算储蓄的时长
     * @param d 结算开始日期
     * @return  时长
     */
    public int minus(Data d){
        return this.totalDays - d.totalDays;
    }

    public void show(){
        System.out.println(getYear()+" - "+getMonth()+"-"+getMonth());
    }
}
----------------ACCUMULATOR----------------------
public class Accumulator {
    private Data lastData;
    private double value;
    private double sum;

    public Accumulator(Data data,double value) {
        lastData = data;
        this.value = value;
        sum = 0;
    }

    public double getSum(Data data) {
        return sum + value*(data.minus(lastData));
    }

    public void change(Data data,double value) {
        sum = getSum(data);
        lastData = data;
        this.value = value;
    }

    public void reset(Data data,double value) {
        lastData = data;
        this.value = value;
        sum = 0;
    }
}


  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目名称:Bank Account Management System 银行账户管理系统 简称BAM 项目描述:这是一个基于C/S结构的银行账户在线管理系统,用户可以通过ATM终端界面来操作自己的银行账户. 项目实施方式:这是一个同步练习,随着达内CoreJava课程的深入,这个项目将趋于完整,学员的任务是随着知识点的深入,完成每一个进阶的项目要求. 项目一 练习1:(面向对象基础语法) 写一个账户类(Account),属性: id:账户号码 长整数 password:账户密码 name:真实姓名 personId:身份证号码 字符串类型 email:客户的电子邮箱 balance:账户余额 方法: deposit: 存款方法,参数是double型的金额 withdraw:取款方法,参数是double型的金额 构造方法: 有参和无参,有参构造方法用于设置必要的属性 练习2:(封装) 将Account类作成完全封装,注意:要辨别每个属性的set/get方法是否需要公开 练习3:(继承,多态) 银行的客户分为两类,储蓄账户(SavingAccount)和信用账户(CreditAccount),区别在于储蓄账户不允许透支,而信用账户可以透支,并允许用户设置自己的透支额度. 注意:CreditAccount需要多一个属性 ceiling 透支额度 为这两种用户编写相关的类 同时要求编写Bank类,属性: 1.当前所有的账户对象的集合,存放在数组中 2.当前账户数量 方法: 1.用户开户,需要的参数:id,密码,密码确认,姓名,身份证号码,邮箱,账户类型(int),返回新创建的Account对象 2.用户登录,参数:id,密码 返回Account对象,提示 用s1.equals(s2)判断s1和s2两个字符串内容是否相等 3.用户存款,参数:id,存款数额,返回修改过的Account对象 4.用户取款,参数:id,取款数额,返回修改过的Account对象 5.设置透支额度 参数:id,新的额度 ,返回修改过的Account对象.这个方法需要验证账户是否是信用账户 用户会通过调用Bank对象以上的方法来操作自己的账户,请分析各个方法需要的参数 另外,请为Bank类添加几个统计方法 1.统计银行所有账户余额总数 2.统计所有信用账户透支额度总数 写个主方法测试你写的类 项目二 练习4:(语言高级特性,三个修饰符) 1.修改Account类,银行用户的账号(id)是自动生成的,初始值为100000,第一个开户的用户id为100001,第二个为100002,依此类推. 提示:构造对象的时候采用static属性为id赋值 2.对于Account类,有两个方法,存款方法和取款方法,请修改这两个方法. 存款方法改为不允许子类修改 取款方法根据不同的子类而不同,因此,改为抽象方法,在两个子类中分别实现 3.将Bank类作成单例 项目三 练习5:(接口) 为SavingAccount和CreditAccount各自添加一个子类 LoanSavingAccount类:用户可以贷款,不可以透支 LoanCreditAccount类:用户可以贷款,可以透支 说明:贷款和透支是不一样的,透支指的是账户余额小于0,而贷款用户需要一个贷款额的属性. 在ATM机上,用户可以选择贷款,也可以选择还贷款,而还贷款就是要把账户余额上的资金转到贷款额上 例如:用户余额10000元,贷款额100000元,用户可以选择还款5000元,则用户余额变为5000,贷款额变为95000元. 利用接口来抽象出LoanSavingAccount类和LoanCreditAccount类的共性 接口中的方法: requestLoan:贷款 payLoan:还贷 getLoan:获取用户贷款总额 为Bank类添加三个方法, 贷款:参数 id,贷款额,返回修改过的Account对象 还贷款:参数 id,还款额,返回修改过的Account对象 统计所有账户贷款的总数 练习6:(Object) 为Account类及其子类添加toString方法和equals方法 项目四 练习7:(Exception) 为BAM添加几个异常类 BalanceNotEnoughException :用于取钱的时候余额不足的情况(包括账户余额超过透支额的情况) RegisterException:用于开户异常的情况,例如密码两次输入不一致等情况 LoginException:用户登录异常的情况,例如id错误,密码错误 LoanException:贷款额不能为负数,如果用户试图将贷款额置为负数,则会抛出这个异常 以上四个异常类有一个共同的父类 BusinessException 并妥善的处理这些异常 项目五 练习8:(集合) 改写Bank类,采用集合的方式来管理多个Account对象 为Bank类添加一个方法 打印所有用户的总资产排名 说明:一个用户可能会有多个账号,以身份证号为准.总资产指多个账户余额的总和,不需要考虑贷款账户的贷款额 项目六 练习9:(GUI) 为BAM添加用户界面 需要以下几个类: BAMClient 其中会包含一个Frame,这是用户主界面 MainPanel:主界面,用户可以选择开户或者登录 RegisterPanel:用户开户具体用到的界面 LoginPanel:用户登录需要的界面 BusinessPanel:界面上会显示账户的功能 至少包括存款和取款,对于可透支的用户,还允许用户修改透支额度,对于贷款用户,还允许用户贷款和还贷款 注:本练习的界面布局不做要求,请阅读现有代码,添加事件处理代码 提示:在开户或者登录之后都会跳到BusinessPanel,而用户点击了交易之后,界面停留在BusinessPanel 要随时注意在BusinessPanel上根据数据的变化更新显示信息 项目七 在该加资源保护的地方加上,没有标准 项目八 练习10:(I/O) 修改Bank类,账户信息会采用对象序列化的方式存放在文件中.当Bank对象生成的时候会读取文件,设置账户集合.当账户信息改变的时候,会随时更新文件 设计一个FileDAO类(文件数据访问对象),负责对文件的访问,包括存放账户,提取账户等方法,在Bank类中,会通过FileDAO对象来访问文件 注意:如果已有的账户对象会存在文件中,那么为新的账户对象分配id的做法也应相应的改变,过去的用static属性的做法不再合适,应该改为,把下一个可用的id存放在一个文件中,每创建一个新对象的时候都会读取这个文件,获得新对象的id,并且修改文件中的id,使其加1.这个工作可以放在Account类的构造方法中 项目九 练习11:(网络) 在现有的BAM中,用户是通过界面直接访问Bank对象的,将其改为C/S结构,由界面充当客户端,通过TCP协议访问服务器端的Bank对象. 提示:客户端和服务器端需要通过对象来传递信息,这里会使用对象序列化技术.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值