《Java从入门到放弃》JavaSE篇:综合练习——单身狗租赁系统(数组版)
因为现在只学习了基本语法,所以在综合练习之前,先补充关于方法概念。
方法的作用:把一系列的代码放在一起,然后再取个别名。之后通过这个别名的调用,就相当于执行了这一系列的代码。
方法的语法:([]中的内容表示是可选的)
public 返回值类型 方法名(参数类型 参数名[,参数类型 参数2 ...]){ //代码块 //[return 数据]; }
方法的例子:
public static void main(String[] args) { loop(); //调用方法 loop(); //再次调用 } /** * 方法功能:计算从1到20的和 * static:表示静态,这个关键字在后面讲面向对象时来解释 * void:表示没有返回值 */ public static void loop(){ int num = 20; int sum = 0; for (int i = 1; i <= num; i++) { sum += i; } System.out.println("结果为:"+sum); }
方法就讲到这儿吧,下面开始今天的内容。
========================永远的分割线君========================
单身狗租赁系统功能分析:
因为还没有学习面向对象,所以我们所有的代码都写在单独的一个类文件中,然后再在main中调用。现阶段只需要知道这个语法,不用管概念。
第一步:搭建项目架构
创建SingleDogManager类,里面包含单身狗的数组和所有的功能方法:
public class SingleDogManager { //保存单身狗信息 String[] id = new String[100]; //编号 String[] nickname = new String[100];//昵称 int[] gender = new int[100]; //性别:0.女 1.男 int[] state = new int[100]; //状态:0.未借出 1.已借出 Date[] date = new Date[100]; //借出日期:Date是日期类型(格式:'2017-03-11 08:34:21') //显示主菜单 public void mainMenu(){ } //查看 public void show() { } //新增 public void add(){ } //删除 public void delete(){ } //借出 public void loan(){ } //归还 public void repay(){ } }
第二步:编写主菜单功能
主菜单当然就是主要显示菜单用滴,在主菜单上选择功能可以调用对应的方法,在对应方法中应该可以返回主菜单。分析发现,在查看、新增、删除等方法中,执行完后都需要让用户返回主菜单,所以我们把返回主菜单再单独写一个方法。
public class SingleDogManager { //保存单身狗信息 String[] id = new String[100]; //编号 String[] nickname = new String[100];//昵称 int[] gender = new int[100]; //性别:0.女 1.男 int[] state = new int[100]; //状态:0.未借出 1.已借出 Date[] date = new Date[100]; //借出日期:Date是日期类型(格式:'2017-03-11 08:34:21') //因为在很多方法中都需要使用输入对象,所以定义到最外面,那么在每个方法中都可以使用了 Scanner input = new Scanner(System.in); //显示主菜单 public void mainMenu(){ System.out.println("======================"); 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("======================"); //注意,如果用户输入了1~6之外的数字,需要让他重新输入(还没学习异常,不考虑异常的情况) int num = 6; do{ System.out.print("请选择:"); num = input.nextInt(); switch (num) { case 1: show(); break; case 2: add(); break; case 3: delete(); break; case 4: loan(); break; case 5: repay(); break; case 6: System.out.println("客官,下次再来玩哟~!"); break; default: System.out.println("输入的啥玩意啊,我只认识1,2,3,4,5,6!!!"); break; } }while(num>6 || num<1); } //查看 public void show() { System.out.println("======================"); System.out.println("====>查看"); System.out.println(); goMainMenu(); } //新增 public void add(){ System.out.println("======================"); System.out.println("====>添加"); System.out.println(); goMainMenu(); } //删除 public void delete(){ System.out.println("======================"); System.out.println("====>删除"); System.out.println(); goMainMenu(); } //借出 public void loan(){ System.out.println("======================"); System.out.println("====>借出"); System.out.println(); goMainMenu(); } //归还 public void repay(){ System.out.println("======================"); System.out.println("====>归还"); System.out.println(); goMainMenu(); } //返回主菜单 public void goMainMenu(){ System.out.print("按任意键后回车返回主菜单:"); String in = input.next(); mainMenu(); } }
在main中编写如下代码就可以测试运行效果了:
public static void main(String[] args) { //创建一个管理对象 SingleDogManager sdm = new SingleDogManager(); //调用管理对象的主菜单方法 sdm.mainMenu(); }
结果:
经测试,项目框架已经搭建OK了。接下来就是一个一个实现功能了,一般软件在运行时都会有个初始化过程,我们这个项目可以在运行的时候就初始化一些单身狗信息(一个店开业时,总要有商品可以租售吧 - -)。所以可以再添加一个初始化方法。
//初始化信息 public void init(){ //第一只 id[0] = "3366"; nickname[0] = "旺财"; gender[0] = 1; state[0] = 0; date[0] = null; //未借出时借出日期为空值 //第二只 id[1] = "5142"; nickname[1] = "黑寡妇"; gender[1] = 0; state[1] = 1; //Date(年,月,日),年是在1900年的基础上加,月的范围0-11,天的范围1-31 date[1] = new Date(117,7,25); //第三只 id[2] = "9527"; nickname[2] = "小强"; gender[2] = 0; state[2] = 0; date[2] = null; }
main方法修改,在调用主菜单之前,先初始化数据。
public static void main(String[] args) { SingleDogManager sdm = new SingleDogManager(); sdm.init(); //初始化 sdm.mainMenu(); //执行主菜单方法 }
第三步:编写查看功能
因为日期类型默认显示效果是“Wed Aug 30 10:37:43 CST 2017”这样滴,所以单独写个方法用来进行日期类型的输出
//查看 public void show() { System.out.println("======================"); System.out.println("====>查看"); System.out.println(); //查看时注意不要把数组中的空元素进行输出了 System.out.println("编号\t昵称\t性别\t状态\t借出日期"); System.out.println("==========================================="); for (int i = 0; i < id.length; i++) { if(id[i]!=null){ System.out.println(id[i]+"\t"+nickname[i]+"\t"+ (gender[i]==0?"女":"男") + "\t"+ (state[i]==0?"未借出":"已借出\t"+toDate(date[i]))); } } System.out.println("==========================================="); goMainMenu(); } /** * 因为日期类型默认显示效果是“Wed Aug 30 10:37:43 CST 2017”这样滴 * 所以单独写个方法用来进行日期类型的输出 * private 表示该方法只能当前这个类的内部使用,具体作用后面会详细讲 * @param 输入日期类型的数据 * @return 返回'xxxx-xx-xx'格式的日期 */ private String toDate(Date d){ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); return sdf.format(d); }
注意:
在循环遍历数组元素时,记得把null元素过滤掉。
运行效果:
第四步:新增功能
新增数据两个要点:1.找到第一个空的位置,2.新增的数据肯定是未借出的,所以只需要输入昵称和性别即可(编号自动生成4位数)。
//新增 public void add(){ System.out.println("======================"); System.out.println("====>添加"); System.out.println(); for (int i = 0; i < id.length; i++) { //找到第一个空的位置 if(id[i]==null){ id[i] = newID(); //自动生成新编号 System.out.print("请输入昵称:"); nickname[i] = input.next(); System.out.print("请选择性别(0.女|1.男):"); gender[i] = input.nextInt(); state[i] = 0; //状态默认为0 //添加完后记得退出循环 break; } } System.out.println("添加完毕!"); goMainMenu(); } //生成新编号(不重复) private String newID() { int num = 0; //保存随机生成的数字 String no; //保存数字的字符串格式 boolean bl; //是否需要重新生成 //因为不知道要生成多少次,所以使用do...while循环 do{ bl = false; //默认不用重新生成 Random random = new Random(); //随机数生成对象 num = random.nextInt(10000); //表示随机得到一个小于10000的整数 no = String.format("%04d", num);//转换成字符串,如果不够4位,前面补0 //判断是否与数组中的元素重复 for (int i = 0; i < id.length; i++) { if(no.equals(id[i])){ bl = true; //数据重复了,需要重新生成 break; } } }while(bl); return no; }
运行效果:
第五步:删除
删除时需要注意:1.已出租的不能删除,2.找不到的必须提示不存在
//删除 public void delete(){ System.out.println("======================"); System.out.println("====>删除"); System.out.println(); System.out.print("请输入编号:"); String no = input.next(); int i; for (i = 0; i < id.length; i++) { if(id[i]!=null && no.equals(id[i])){ //要注意,已租出去的单身狗是不能删除的,必须归还后才能删除 if(state[i]==1){ System.out.println("该单身狗已租出还未归还,不能删除!"); break; } //因为是通过编号来判断数据是否存在,所以只需要把id清空即可 id[i] = null; //把字符串数组中对应的数据变成null就相当于删除了 System.out.println("删除成功!"); break; } } //如果循环完了都没找到这个编号的单身狗,则说明它不存在 if(i==id.length){ System.out.println("查无此狗!"); } goMainMenu(); }
运行效果:
已借出和不存在的数据,各位看官可以自己试试哈。
第六步:借出
出租的话,肯定是能让用户选择的,所以我们先显示出所有的单身狗,然后再让用户输入编号再借出。要注意:已借出的不能再次借出。按道理应该只显示出所有未出租的,这段代码和前面的查看非常类似,很多新手在这儿就会把前面的代码Copy过来再改改就继续用了。
但是!!!!!
我们可以使用重构代码的方式,把可以重复使用的代码单独放到一个方法用反复调用,千万不要改相似度太高的重复代码!!!!
============================================================
重构操作步骤:
1.选中你打算复制了去改的这一段代码,然后点右键,再根据图选择对应选项。
2.给方法取名
3.因为该方法需要按不同的需求显示不同的数据,所以加一个参数用来决定如果显示数据,同时修改一下代码
/** * 因为现在有两种情况,一种是显示所有,一种是显示所有未借出的 * 可惜我们还没有学习枚举类型,这儿就简单处理一下,加个整型参数 * @param dogState -1表示查询所有, 0表示查询未借出 */ private void showDog(int dogState) { //查看时注意不要把数组中的空元素进行输出了 System.out.println("编号\t昵称\t性别\t状态\t借出日期"); System.out.println("==========================================="); for (int i = 0; i < id.length; i++) { if(id[i]!=null){ if(dogState==-1){ System.out.println(id[i]+"\t"+nickname[i]+"\t"+ (gender[i]==0?"女":"男") + "\t"+ (state[i]==0?"未借出":"已借出\t"+toDate(date[i]))); } else if(state[i]==0){ System.out.println(id[i]+"\t"+nickname[i]+"\t"+ (gender[i]==0?"女":"男") + "\t未借出"); } } } System.out.println("==========================================="); } }
4. 修改查看方法中的代码,给方法传值-1
//查看 public void show() { System.out.println("======================"); System.out.println("====>查看"); System.out.println(); showDog(-1); //传值-1表示查询所有 goMainMenu(); }
============================================================
OK,我们继续完成借出的代码:
//借出 public void loan(){ System.out.println("======================"); System.out.println("====>借出"); System.out.println(); showDog(0); //显示所有未借出的单身狗 System.out.print("请输入编号"); String no = input.next(); int i; for (i = 0; i < id.length; i++) { if(id[i]!=null && no.equals(id[i])){ //要注意,已租出去的单身狗是不能再次出租 if(state[i]==1){ System.out.println("该单身狗已租出!"); break; } state[i] = 1; //将状态改为1(已借出) date[i] = new Date(); //将借出日期设置为当前日期 System.out.println("借出完毕!"); break; } } //如果循环完了都没找到这个编号的单身狗,则说明它不存在 if(i==id.length){ System.out.println("查无此狗!"); } goMainMenu(); }
运行效果:
第七步:归还
因为是给广大单身狗或单身猿们,所以我们都是免费出租(其实是懒,因为要计算租金又要多写好些代码 - -),哈哈哈!!!
归还和借出是刚好相反的操作,所以我们可以再次修改showDog的代码,让他可以传值1进去显示所有已借出的Dog。另外,因为和借出的功能非常类似,所以同样可以把借出中的相同代码重构成方法,然后再调用。
1.修改showDog()方法中的代码,再加上else部分,因为这儿只有三种状态,所以可以这样写,如果状态更多的话,那代码还可以优化:
if(dogState==-1){ System.out.println(id[i]+"\t"+nickname[i]+"\t"+ (gender[i]==0?"女":"男") + "\t"+ (state[i]==0?"未借出":"已借出\t"+toDate(date[i]))); } else if(dogState==0 && state[i]==0){ System.out.println(id[i]+"\t"+nickname[i]+"\t"+ (gender[i]==0?"女":"男") + "\t未借出"); } else if(dogState==1 && state[i]==1){ System.out.println(id[i]+"\t"+nickname[i]+"\t"+ (gender[i]==0?"女":"男") + "\t已借出\t"+toDate(date[i])); }
2.重构借出的代码
/** * 根据不同的操作,改变Dog的状态 * @param dogState 要改变的状态 0.归还 1.借出 */ private void changeDogState(int dogState) { System.out.print("请输入编号"); String no = input.next(); int i; for (i = 0; i < id.length; i++) { if(id[i]!=null && no.equals(id[i])){ if(dogState==1){ //要注意,已租出去的单身狗是不能再次出租 if(state[i]==1){ System.out.println("该单身狗已租出!"); break; } state[i] = 1; //将状态改为1(已借出) date[i] = new Date(); //将借出日期设置为当前日期 System.out.println("借出完毕!"); } else{ //要注意,未租出的Dog是不能归还的 if(state[i]==0){ System.out.println("该单身狗未出租,不能归还!"); break; } state[i] = 0; //将状态改为0(未借出) date[i] = null; //将借出日期设置为空值 System.out.println("归还完毕!"); } break; } } //如果循环完了都没找到这个编号的单身狗,则说明它不存在 if(i==id.length){ System.out.println("查无此狗!"); } }
3.借出和归还的代码:
//借出 public void loan(){ System.out.println("======================"); System.out.println("====>借出"); System.out.println(); showDog(0); //显示所有未借出的单身狗 changeDogState(1); goMainMenu(); } //归还 public void repay(){ System.out.println("======================"); System.out.println("====>归还"); System.out.println(); showDog(1); //显示所有已借出的Dog changeDogState(0); //归还后状态改为0 goMainMenu(); }
运行效果:
OK,一个最精简版本的《单身狗租赁系统》到此就告一段落了,建议各位新手看官先自己尝试着实现,如果碰到问题了,再参考上面的代码(上面代码只是面向初学者,所有很多地方是不够严谨的,特此声明)。文章下面有参考源码。
如果有已经完成的看客,可以再尝试加些功能上去,比如计算租金,修改某个Dog的信息等。
“软件思维”博客地址:51CTO,博客园,感兴趣的小伙伴可以去看相关的其它博文。