综合练习题让你编程能力真正进阶。
文章适合于初学或即将开始学习JAVA的小伙伴,你将看到鲜活的真实错误案例,还有复盘的注意事项。
练习题背景
构造方法、静态关键字、封装,还有数组都算是JAVA编程的核心基础。
这两个练习题对我最大的挑战表面上是“构造方法”、“数组”的技法应用,实际是面向对象程序思路框架的搭建。第一题数组是对象的属性,第二题对象是数组的元素,不得不说都是跨了很多知识点的经典题目。
题目一:使用一维数组,模拟栈数据结构
1、这个栈可以存储java中的任何引用类型的数据;
2、在栈中模拟push方法压栈;(含“栈满了”的提示信息);
3、在栈中模拟pop方法弹栈;(含“栈空了”的提示信息)
题一主要围绕一个包含数组属性的类,并在类文件中编写响应的push方法、pop方法。
修改前代码
以下是main程序代码:
public class stacktest {
public static void main(String[] args) {
//创建对象
MyStack mystk = new MyStack(new Object[]{1,2,3,5},5);
//main函数只放声明,初始化统一体现在main程序中
//通过push方法增加数据,包含栈底即将满时报错
mystk.push(1);
//通过pop方法推出数据,包含栈底即将为空时报错
mystk.pop();
}
}
以下是核心类文件代码:
class MyStack {
private Object[] elements;
private int ix; //栈帧;
//无参构造函数 =========================
public MyStack(){
elements = new Object[5];
ix = -1; }
//创建push方法;
public void push(Object obj){
if (ix < elements.length-1){
elements[ix] = obj;
System.out.println("成功把新元素"+ obj +"压入到下标为"+ ix + "的位置");
ix++;//错误标记_这样会导致栈刚堆到满时下标会超出,应该使移完下标再赋值}else {
System.out.println("栈满了"); }
}
//创建pop方法;
public void pop(){
if (ix>=0){
Object objtemp = elements[ix];
elements[ix]=null;
System.out.println("成功把位置下标为"+ ix + "的栈顶元素"+objtemp+ "弹出");//这里的对象不需要toString?
ix--; }else {
System.out.println("栈空了"); }
}
}
修改后代码:
以下是main程序代码:
public class stacktest {
public static void main(String[] args) {
//创建对象
MyStack mystk = new MyStack();
//main函数只放声明,初始化统一体现在main程序中
//通过push方法增加数据,包含栈底即将满时报错
mystk.push(1);
//通过pop方法推出数据,包含栈底即将为空时报错
mystk.pop();
}
}
以下是核心类文件代码:
class MyStack {
private Object[] elements;
private int ix; //栈帧;
//无参构造函数 =========================
public MyStack(){
elements = new Object[5];
ix = -1; }
//创建push方法;
public void push(Object obj){
if (ix < elements.length-1){
ix++;
elements[ix] = obj;
System.out.println("成功把新元素"+ obj +"压入到下标为"+ ix + "的位置");
}else {
System.out.println("栈满了"); }
}
//创建pop方法;
public void pop(){
if (ix>=0){
Object objtemp = elements[ix];
elements[ix]=null;
System.out.println("成功把位置下标为"+ ix + "的栈顶元素"+objtemp+ "弹出");//这里的对象不需要toString?
ix--; }else {
System.out.println("栈空了"); }
}
}
题目二:用到二维数组编写酒店管理系统相关程序,模拟订房、退房、打印所有房间状态等功能
1、每一个房间Room应该有:房间编号、房间类型、房间是否空闲;
2、输入房间编号可以预定房间;
3、输入房间编号可以退房;
4、输入某个执行可以查看所有房间状态
题二相对难一些,涉及到二维数组,而且是对象数组。具体代码分成了“房间类”、“酒店类”、“main程序”。
单独拆解出“酒店类”,而且还和“房间类”存在复杂的嵌套关系,主要是由于“房间对象初始化时”、“查看全部房间状态时”都有一块二维数组遍历的代码块,放main程序太长了。
修改前代码
以下是main程序代码:
public class hoteltest {
public static void main(String[] args) {
//初始化一个酒店
Hotel ht = new Hotel();
Scanner scan = new Scanner(System.in);
System.out.println("请输房间号,如'0113即一楼第13间':");
//s.nextLine();//错误标记,scan仍然是一个引用
//预定某个房间
ht.book(s);
//退订某个房间
ht.unbook(s);
//查看所有房间状态
allbookstatus(ht);//错误标记_执行方法时,只有引用.方法名(),没有方法名(引用)
}
}
以下是酒店类代码:
public class Hotel {
//“拥有房间的声明”
Room[][] myrm;
//无参构造方法:
public Hotel(){
myrm = new Room[3][15];
//这一步只是给数组元素进行初始化分配空间,还需要给每个元素初始化分配空间; 不仅适用于对象数组,也适用于其他引用数据类型的数组;
for (int i=0; i<3; i++){
for (int j=0; j<15; j++){
Room room = new Room(i, j); //错误标记_此处应该要到引用,上方已声明,不能新建引用:Room room; }
}
}
//预订房间
public void book(String s){
int floor = Integer.parseInt(s.substring(0,2)) - 1;
int num = Integer.parseInt(s.substring(2,4)) - 1;
myrm[floor][num].book();
//嵌套类的方法重名没关系,对象所归属的类不同;}
//退订房间
public void unbook(String s){
int floor = Integer.parseInt(s.substring(0,1)) - 1;
//错误标记_endindex应该取2不是1
int num = Integer.parseInt(s.substring(2,4)) - 1;
myrm[floor][num].unbook(); }
//查看所有房间状况
public void allbookstatus(){ //错误标记_方法名(a)、要加void for (int i=0; i<myrm.length; i++){
for (int j=0; j<myrm[0].length; j++){
switch (myrm[i][j].getRoomstatus()){//封装
case 0:
System.out.print("房间号"+myrm[i][j].roomnumber+"的状态:"+"空闲,");
break;
case 1:
System.out.print("房间号"+myrm[i][j].roomnumber+"的状态:"+"预定中,");
break;
case 2:
System.out.print("房间号"+myrm[i][j].roomnumber+"的状态:"+"使用中,");
break; }
}
System.out.println(""); }
}
}
以下是房间类代码:
public class Room{
String roomnumber;
int roomtype;
private int roomstatus; //封装私有化
public int getRoomstatus() {
return roomstatus; }
public void setRoomstatus(int roomstatus) {
this.roomstatus = roomstatus; }
public void Room(){//错误标记_此处不能有void,有对应普通方法,使得缺少无参构造函数初始化为空值
roomtype = (int)(Math.random()*3);//0标间,1大床房,2豪华间,3商务间
roomstatus = (int)(Math.random()*2);//0空间,1预定中,2使用中 }
public Room(int floor, int num){
this.roomnumber = String.format("%02d%02d", floor, num);
roomtype = (int)(Math.random()*3);//0标间,1大床房,2豪华间,3商务间
roomstatus = (int)(Math.random()*2);//0空间,1预定中,2使用中 }
public void book(){
if (roomstatus==1){
System.out.println("预定不成功,该房间已经处于预定中状态。"); }else if (this.roomstatus==2){
System.out.println("预定不成功,该房间已经处于使用中状态。"); }else {
roomstatus = 1;
System.out.println("预定成功");}
}
//退订房间
public void unbook(){
roomtype = 0;
System.out.println("退订成功"); }
}
修改后代码
以下是main程序代码:
public class hoteltest {
public static void main(String[] args) {
//初始化一个酒店
Hotel ht = new Hotel();
Scanner scan = new Scanner(System.in);
System.out.println("请输房间号,如'0113即一楼第13间':");
String s = scan.nextLine();
//预定某个房间
ht.book(s);
//退订某个房间
ht.unbook(s);
//查看所有房间状态
ht.allbookstatus();//错误标记
}
}
以下是酒店类代码:
public class Hotel {
//“拥有房间的声明”
Room[][] myrm;
//无参构造方法:
public Hotel(){
myrm = new Room[3][15];
//这一步只是给数组元素进行初始化分配空间,还需要给每个元素初始化分配空间;不仅适用于对象数组,也适用于其他引用数据类型的数组;
for (int i=0; i<3; i++){
for (int j=0; j<15; j++){
myrm[i][j] = new Room(i, j); //错误标记_此处应该要到引用,上方已声明,不能新建引用:Room room; }
}
}
//预订房间
public void book(String s){
int floor = Integer.parseInt(s.substring(0,2)) - 1;
int num = Integer.parseInt(s.substring(2,4)) - 1;
myrm[floor][num].book();
//嵌套类的方法重名没关系,对象所归属的类不同;}
//退订房间
public void unbook(String s){
int floor = Integer.parseInt(s.substring(0,2)) - 1;
//错误标记_endindex应该取2不是1
int num = Integer.parseInt(s.substring(2,4)) - 1;
myrm[floor][num].unbook(); }
//查看所有房间状态
public void allbookstatus(){ //错误标记_方法名(a)、要加void for (int i=0; i<myrm.length; i++){
for (int j=0; j<myrm[0].length; j++){
switch (myrm[i][j].getRoomstatus()){//封装
case 0:
System.out.print("房间号"+myrm[i][j].roomnumber+"的状态:"+"空闲,");
break;
case 1:
System.out.print("房间号"+myrm[i][j].roomnumber+"的状态:"+"预定中,");
break;
case 2:
System.out.print("房间号"+myrm[i][j].roomnumber+"的状态:"+"使用中,");
break; }
}
System.out.println(""); }
}
}
以下是房间类代码:
public class Room{
String roomnumber;
int roomtype;
private int roomstatus; //封装私有化
public int getRoomstatus() {
return roomstatus; }
public void setRoomstatus(int roomstatus) {
this.roomstatus = roomstatus; }
public Room(){//错误标记_此处不能有void,有对应普通方法,使得缺少无参构造函数初始化为空值
roomtype = (int)(Math.random()*3);//0标间,1大床房,2豪华间,3商务间
roomstatus = (int)(Math.random()*2);//0空间,1预定中,2使用中 }
public Room(int floor, int num){
this.roomnumber = String.format("%02d%02d", floor, num);
roomtype = (int)(Math.random()*3);//0标间,1大床房,2豪华间,3商务间
roomstatus = (int)(Math.random()*2);//0空间,1预定中,2使用中 }
public void book(){
if (roomstatus==1){
System.out.println("预定不成功,该房间已经处于预定中状态。"); }else if (this.roomstatus==2){
System.out.println("预定不成功,该房间已经处于使用中状态。"); }else {
roomstatus = 1;
System.out.println("预定成功");}
}
//退订房间
public void unbook(){
roomtype = 0;
System.out.println("退订成功");
总结
通过视频自学经常为了追求进度而实际没有深入思考底层逻辑,遇到真正的综合题就原形毕露,感觉真是“寸码难敲”。好在做习题相当于带着问题去复习,事半功倍,尤其是错过的地方印象更深刻了。
这次让我重查并且印象深刻的关键知识点有:
主题 | 知识点 |
---|---|
构造方法 | 不需要指定返回值类型、不能写void(写上就成为普通方法) |
构造方法 | 构造方法的方法名必须和类名保持一致 |
构造方法 | 构造方法的作用:创建对象、给对象的各个属性赋初始值 |
构造方法 | 返回值、返回值类型都不需要写(实际有返回值,自动返回) |
构造方法 | 当一个类没有定义构造方法,系统默认给该类提供一个无参数的构造方法,缺省构造器 |
构造方法 | 多个实参列表组合的构造方法已经构成“重载” |
Static关键字 | 修饰“静态变量”、“静态方法”,都是类级别的特征,和具体对象无关 |
Static关键字 | 用类名.方法名,不用对象(static在初始化时就已经分配内存,所以不需要new来分配内存): 通俗点就是“无对象要加static,有对象不加static” |
封装 | 作用是“提高对象属性的安全性”,用private关键字来体现 |
封装 | 要结合setter()、getter()方法 |
最后,谢谢大家查看,我们在打造自学JAVA小部落,希望有同样目标的小伙伴和大佬加入。