Java项目一(案例):家庭收支记账软件
项目概述
软件功能
记录家庭的收入、支出,并能够打印收支明细表。
项目说明
项目采用分级菜单方式,整个表案例分为两个类文件,一个用于存储主程序,另一个用于存储自定义工具包。因为还未涉及文件存储方面的知识,故该程序并不会永久保存输入数据。
涉及Java知识点
1.变量的定义
2.基本数据类型的使用
3.循环语句
4.分支语句
5.方法声明、调用和返回值的接受
6.简单的屏幕输出格式控制
7.导入包并调用相关方法
软件需求说明
假设家庭起始的生活基本金为10000元。
每次登记收入(菜单2)后,收入的金额应累加到基本金上,并记录本次收入明细,以便后续的查询。
每次登记支出(菜单3)后,支出的金额应从基本金中扣除,并记录本次支出明细,以便后续的查询。
查询收支明细(菜单1)时,将显示所有的收入、支出明细列表。
程序代码示例
FamilyAccount.class文件
public class FamilyAccount {
public static void main(String[] args) {
boolean loopFlag = true; //用标记做do-while循环的循环条件
double basic = 10000; //定义生活基本金,初始金额,用来记录每次收支变化后的金额
String details = "收支 \t 账户金额 \t 收支金额 \t 说明\n"; //用于记录用户收入和支出的详情
//使用do-while循环确保程序至少执行一次
do {
//定义用户界面,每进行一次循环就会显示一次选项界面
System.out.println("-------------------家庭收支记账软件-------------------");
System.out.println();
System.out.println(" 1 收支明细");
System.out.println(" 2 登记收入");
System.out.println(" 3 登记支出");
System.out.println(" 4 退出\n");
System.out.print(" 请选择(1-4):");
//获取用户的选择,并根据switch分支结构选择程序执行模块
char menu = Utility.readMenuSelection(); //利用自定义工具类Utility中的菜单选择函数获取用户的选择
switch (menu) {
case '1': {
//选择1 收支明细显示界面
System.out.println("-------------------当前收支明细记录-------------------");
System.out.println(details); //显示用来记录用户收支详情的details变量
System.out.println("---------------------------------------------------\n");
break;
}
case '2': {
//选择2 登记收入
System.out.print("本次收入金额:");
double moneyIn = Utility.readNumber(); //调用自定义工具类Utility中读取金额收入与支出的函数
System.out.print("本次收入说明:");
String info_in = Utility.readString(); //调用自定义工具栏Utility中读取收入与支出说明的函数
//处理金额变化
basic += moneyIn;
//处理details,每记录一次收入,在details变量上叠加一次相关的字符串
details += "收入 \t " + basic + " \t " + moneyIn + " \t " + info_in + "\n";
//完成收入登记并点击回车后显示”登记完成“字样
System.out.println("----------------------登记完成-----------------------\n");
break;
}
case '3': {
//选择3 登记支出
System.out.print("本次支出金额:");
double moneyOut = Utility.readNumber(); //调用自定义工具类Utility中读取金额收入与支出的函数
System.out.print("本次支出说明:");
String info_Out = Utility.readString(); //调用自定义工具栏Utility中读取收入与支出说明的函数
//处理金额变化
basic -= moneyOut;
//处理details,每记录一次支出,在details变量上叠加一次相关字符串
details += "支出 \t " + basic + " \t " + moneyOut + " \t " + info_Out + "\n";
//完成支出登记并点击回车后显示”登记完成“字样
System.out.println("----------------------登记完成-----------------------\n");
break;
}
case '4': {
System.out.print("确认是否退出(Y/N):");
//调用自定义工具类Utility中的确认选择函数来读取用户输入的指令
char Selection = Utility.readConfirmSelection();
//若读取到的选择为Y,则标记赋值为false,终止循环;否则无事发生重新循环
if (Selection == 'Y') {
loopFlag = false;
}
}
}
}while(loopFlag);
System.out.println("再见!!!");
}
}
自定义Utility.class工具类
自定义的 Utility工具类:
将不同的功能封装为方法,就是可以直接通过调用方法使用它的功能,而无需考虑具体的功能实现细节。
import java.util.Scanner; //导入Scanner包,因为工具类中使用到了输入的相关方法
public class Utility {
//这个是自定义用来调用的工具类,故不需要在此定义main()语句了
private static Scanner scanner = new Scanner(System.in); //Private 变量只能在包含其声明的模块中使用
/*
定义一个readKeyBoard函数,用于从键盘读取参数限制长度的一行内容
*/
private static String readKeyBoard(int limit) {
String line = "";
while (scanner.hasNext()) {
/*
Scanner类中的hasNext方法读取的是boolean型的值,用于检测输入是否还有其他单词,有则真无则假
官方解释:当执行到hasNext()时,它会先扫描缓冲区中是否有字符,有则返回true,继续扫描。
直到扫描为空,这时并不返回false,而是将方法阻塞,等待你输入内容然后继续扫描。
*/
line = scanner.nextLine(); //将从键盘上读取到的内容赋给line,为字符串类型
if (line.length() < 1 || line.length() > limit) { //当输入字符串长度小于1或输入字符串长度超过参数限制时执行
System.out.print("输入长度(不大于" + limit + ")错误,请重新输入:");
continue; //再次执行循环来读取键盘输入的有意义的值
}
break; //当读取到的字符串符合要求则终止循环,执行循环外的下一条语句返回字符串
}
return line; //返回读取到的指定长度内的字符串字面量
}
/*
用于界面菜单的选择。该方法读取键盘,如果用户键入’1’-’4’中的任意字符,则该方法将读取到的合法键入字符返回。
*/
public static char readMenuSelection() {
char c; //定义一个字符型变量来存储选择
//无限循环for,直到读取到合法的键入字符
for ( ; ; ) {
String str = readKeyBoard(1); //调用同类下的readKeyBoard方法来读取一个键盘中输入的字符串,并赋给str
c = str.charAt(0); //调用java.lang.String类下的charAt方法,用来返回第零个位置的代码单元,即str的首位字符
if (c != '1' && c != '2' && c != '3' && c != '4') {
System.out.print("选择错误,请重新输入:");
} else break; //若读取到的字符合法,则跳出无限循环并执行下面一条语句返回读取到的合法选择
}
return c;
}
/*
用于收入和支出金额的输入。该方法从键盘读取一个不超过4位长度的整数,并将其作为方法的返回值。
*/
public static int readNumber() {
int n;
for ( ; ; ) {
String str = readKeyBoard(4);
/*
try-catch语句块:
try-catch语句是抛出异常的语句。
*/
try { //执行的代码,其中可能有异常。一旦发现异常,则立即跳到catch执行。否则不会执行catch里面的内容
n = Integer.parseInt(str);
/*Integer.parseInt()是把()里的内容转换成整数。
Integer.parseInt(String)遇到一些不能被转换为整型的字符时,会抛出异常
若抛出异常,则执行catch语句块中的语句
*/
break;
} catch (NumberFormatException e) {
//除非try里面执行代码发生了异常,否则这里的代码不会执行
System.out.print("数字输入错误,请重新输入:");
}
}
return n;
}
/*
用于收入和支出说明的输入。该方法从键盘读取一个不超过8位长度的字符串,并将其作为方法的返回值。
*/
public static String readString() {
String str = readKeyBoard(8); //调用同类下的readKeyBoard方法并将读取到的字符串赋给str
return str;
}
/*
用于确认选择的输入。该方法从键盘读取‘Y’或’N’,并将其作为方法的返回值。
*/
public static char readConfirmSelection() {
char c;
for ( ; ; ) {
String str = readKeyBoard(1).toUpperCase();
//toUpperCase用于返回一个新字符串,将原始字符串的小写字母改为大写
c = str.charAt(0); //charAt用于返回给定位置(0为第一个位置)的代码单元
if (c == 'Y' || c == 'N') {
break;
} else {
System.out.print("选择错误,请重新输入:");
}
}
return c;
}
}
程序运行示例