Day17 面向对象版学生管理系统
代码已放在资源里,有需要可自取!!!
1.需求分析
管理的是一个一个的学生对象
学生类:
public class Student{
String name;
char sex;
int age;
String classId;//班级号
String id;//学号
}
学生数据的限制:(StuInfoUtil工具类)
1.名字长度2–16
2.性别必须是男或女
3.年龄18–50
4.班级号长度4
5.学号长度3
怎么判断学生是否相同呢? 班级号+学号(重写equals方法)
管理 --> 数组 - Student[](数组中没有增,所以设置只能放3个元素的数组,然后扩容)
增 - 注意:涉及到扩容
删 - 注意:根据班级号+学号去删除
改 - 注意:修改学生对象里所有的数据
查 - 注意:
根据姓名查询 - 学生数组
根据性别查询 - 学生数组
根据年龄查询 - 学生数组
根据班级号查询 - 学生数组
根据班级号+学号查询 - 学生对象在容器的下标
注意:数据源:存储数据的地方
设计图:
2.项目搭建
2.1 分包
sms:学生管理包
utils:工具包
pojo:实体类
impI:实现接口类
分包示意图:
2.2 编写实体类(Student)
pojo包中放的是学生对象,有无参构造,get、set方法,toString方法,重写equals方法
package com.pcb.pojo;
public class Student{
private String name;
private char sex;
private int age;
private String classId;//班级号
private String id;//学号
public Student() {
}
public Student(String name, char sex, int age, String classId, String id) {
super();
this.name = name;
this.sex = sex;
this.age = age;
this.classId = classId;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getClassId() {
return classId;
}
public void setClassId(String classId) {
this.classId = classId;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
//判断两个学生是否相同
//比较规则:班级号+学号
@Override
public boolean equals(Object obj) {//重写equals
if (this == obj) {
return true;
}
if (obj instanceof Student) {//判断是否是学生类
Student stu = (Student) obj;//强转
if (this.classId.equals(stu.classId) && this.id.equals(stu.id)) {
return true;
}
}
return false;
}
@Override
public String toString() {
return name + "\t" + sex + "\t" + age + "\t" + classId + "\t" + id;
}
}
2.3 编写工具类
utils包中存放的是学生信息合法性的类(就是上面的学生数据的限制)
package com.pcb.utils;
import com.pcb.pojo.Student;
//学生信息合法性的工具类
public interface StuInfoUtil {
public static boolean isStu(Student stu) {
String name = stu.getName();
char sex = stu.getSex();
int age = stu.getAge();
String classId = stu.getClassId();
String id = stu.getId();
if (isName(name) && isSex(sex) && isAge(age) && isClassId(classId) &&isId(id)) {
return true;
}
return false;
}
public static boolean isName(String name){
int len=name.length();//长度
if (len >= 2 && len <= 16) {
return true;
}
return false;
}
public static boolean isSex(char sex){
if (sex == '男' || sex == '女') {
return true;
}
return false;
}
public static boolean isAge(int age){
if (age >= 18 && age <= 50) {
return true;
}
return false;
}
public static boolean isClassId(String classId){
int len=classId.length();
if (len == 4) {
return true;
}
return false;
}
public static boolean isId(String id){
int len=id.length();
if (len == 3) {
return true;
}
return false;
}
}
2.4 编写接口
sms学生管理包放学生管理系统的接口(列出添加、扩容、删除、修改等的接口)
package com.pcb.sms;
import com.pcb.pojo.Student;
public interface StudentManagerSystem {
//type的种类
int NAME = 1;
int SEX = 2;
int AGE = 3;
int CLASS_ID = 4;
int ID = 5;
/**
* 添加学生
* @param stu 学生对象
* @return 添加状态码
*/
public int add(Student stu);
/**
* 数据源扩容
* 扩容机制为原来长度的1.5
*/
public void expansion();
/**
* 删除学生
* @param classId 目标班级号
* @param id 目标学号
* @return 删除状态码
*/
public int delete(String classId,String id);
/**
* 修改学生信息
* @param classId 目标班级号
* @param id 目标学号
* @param type 修改类型:1-修改姓名 2-修改性别 3-修改年龄 4-修改班级号 5-修改学号
* @param val 修改的值
* @return 修改状态码
*/
public int update(String classId,String id,int type,Object val);
/**
* 根据学生查询在数据源中的学生对象的下标
* @param stu 目标学生
* @return 如果有,就返回数据源中的下标。如果没有,就返回-1
*/
public int query(Student stu);
/**
* 根据班级号+学号查询在数据源中的学生对象的下标
* @param classId 目标班级号
* @param id 目标学号
* @return 如果有,就返回数据源中的下标。如果没有,就返回-1
*/
public int query(String classId,String id);
/**
* 根据姓名查询学生对象数组
* @param name 目标姓名
* @return 如果有,返回学生对象数组。如果没有,就返回null
*/
public Student[] getStuByName(String name);
/**
* 根据性别查询学生对象数组
* @param sex 目标性别
* @return 如果有,返回学生对象数组。如果没有,就返回null
*/
public Student[] getStuBySex(char sex);
/**
* 根据年龄段查询学生对象数组
* @param start 开始年龄 - 包含
* @param end 结束年龄 - 排他
* @return 如果有,返回学生对象数组。如果没有,就返回null
*/
public Student[] getStuAge(int start,int end);
/**
* 根据班级号查询学生对象数组
* @param classId 目标班级号
* @return 如果有,返回学生对象数组。如果没有,就返回null
*/
public Student[] getStuClassId(String classId);
/**
* 打印数据源中所有的学生对象
*/
public void printAllStudent();
}
3.添加功能
在ImpI包中的StudentManagerSystemImpl,写下面的添加方法(涉及的到扩容方法·)
@Override
public int add(Student stu) {
//1.判断学生信息合法性
if(!StuInfoUtil.isStu(stu)){
return -1;
}
//2.判断是否有重复学生
if(query(stu) != -1){
return -2;
}
//3.判断是否扩容
if(stus.length == size){
expansion();
}
//4.添加学生
stus[size++] = stu;
return 1;
}
@Override
public void expansion() {
int oldCapacity = stus.length;
int newCapacity = oldCapacity + (oldCapacity>>1);
// Student[] newStus = new Student[newCapacity];
// for (int i = 0; i < stus.length; i++) {
// newStus[i] = stus[i];
// }
// stus = newStus;
stus = Arrays.copyOf(stus, newCapacity);
}
3.1 编写测试类的添加前端页面
在main包的Test类中写前端页面,设置addMenu(Scan,sms),添加菜单
public class Test {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
StudentManagerSystemImpl sms=new StudentManagerSystemImpl();
System.out.println("欢迎使用**学生管理系统");
boolean flag = true;
while(flag){
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("886 - 退出系统");
int num = scan.nextInt();
switch (num) {
case 1:
addMenu(scan, sms);
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
sms.printAllStudent();
break;
case 886:
flag = false;
System.out.println("正在退出**学生管理系统,欢迎下次再来...");
break;
default:
System.out.println("输入错误,请重新输入...");
break;
}
System.out.println("------------------------");
}
scan.close();//关闭资源
}
添加菜单的编写
private static void addMenu(Scanner scan, StudentManagerSystemImpl sms) {// Alt + shift + m
System.out.println("请输入姓名:");
String name = scan.next();
System.out.println("请输入性别:");
char sex = scan.next().charAt(0);//1.输入字符串 2.获取字符串中下标为0的字符
System.out.println("请输入年龄:");
int age = scan.nextInt();
System.out.println("请输入班级号:");
String classId = scan.next();
System.out.println("请输入学号:");
String id = scan.next();
Student stu = new Student(name, sex, age, classId, id);
int addCode = sms.add(stu);
if(addCode == -1){
System.out.println("添加失败 -- 学生信息不合法");
}else if(addCode == -2){
System.out.println("添加失败 -- 有重复学生");
}else if(addCode == 1){
System.out.println("添加成功");
}
}
4.删除功能
为了方便删除,在StudentManagerSystemImpl,写一个无参构造方法,设置初始值,方便测试删除功能(后面可删除此方法)
public StudentManagerSystemImpl() {
stus = new Student[DEFAULT_CAPACITY];
add(new Student("麻生希", '女', 27, "2401", "001"));
add(new Student("椎名空", '女', 23, "2401", "002"));
add(new Student("水菜丽", '女', 21, "2401", "003"));
add(new Student("朝桐光", '女', 31, "2401", "004"));
add(new Student("北岛玲", '女', 36, "2401", "005"));
add(new Student("樱井步", '女', 29, "2401", "006"));
add(new Student("爱田奈奈", '女', 32, "2401", "007"));
add(new Student("水野朝阳", '女', 31, "2401", "008"));
add(new Student("古川伊织", '女', 27, "2401", "009"));
add(new Student("巴得伟", '男', 21, "2401", "010"));
add(new Student("李星乐", '男', 20, "2401", "011"));
add(new Student("北条麻衣", '女', 34, "2402", "001"));
add(new Student("濑亚美莉", '女', 23, "2402", "002"));
add(new Student("三上悠亚", '女', 21, "2402", "003"));
add(new Student("小西满里惠", '女', 31, "2402", "004"));
add(new Student("桃谷绘里香", '女', 27, "2402", "005"));
add(new Student("铃原爱蜜莉", '女', 23, "2402", "006"));
add(new Student("明日花绮罗", '女', 28, "2402", "007"));
add(new Student("京香Julia", '女', 34, "2402", "008"));
add(new Student("巴得伟", '男', 18, "2402", "009"));
add(new Student("张海杰", '男', 20, "2402", "010"));
}
删除功能的实现
@Override
public int delete(String classId, String id) {
//1.判断学生信息合法性
if(!StuInfoUtil.isClassId(classId) || !StuInfoUtil.isId(id)){
return -1;
}
//2.判断是否有该学生
int index = query(classId, id);
if(index == -1){
return -2;
}
//3.删除学生
for (int i = index; i < size-1; i++) {
stus[i] = stus[i+1];//数据移位,把后面的赋值给前一个
}
size--;
return 1;
}
pojo包下的Student类,编写Student的无参构造,只有classId,id
public Student(String classId, String id) {
this.classId = classId;
this.id = id;
}
@Override
public int query(String classId, String id) {
//创建临时学生对象(注意:该学生对象中只有班级号和学号)
Student stu = new Student(classId, id);
int index = query(stu);
return index;
}
思考题://1.判断学生信息合法性
4.1 编写测试类的删除前端页面
case 1:
addMenu(scan, sms);
break;
case 2:
deleteMenu(scan, sms);
break;
删除菜单的方法
private static void deleteMenu(Scanner scan, StudentManagerSystemImpl sms) {
System.out.println("请输入班级号:");
String classId = scan.next();
System.out.println("请输入学号:");
String id = scan.next();
int deleteCode = sms.delete(classId, id);
if(deleteCode == -1){
System.out.println("删除失败 -- 学生信息不合法");
}else if(deleteCode == -2){
System.out.println("删除失败 -- 没有该学生");
}else if(deleteCode == 1){
System.out.println("删除成功");
}
}
5.查询功能
在StudentManagerSystemImpl实现类中,重写以下方法,根据姓名,年龄,性别段,班级号查询的方法
@Override
public Student[] getStuByName(String name) {
//1.验证学生信息合法性
if (! StuInfoUtil.isName(name)) {
return null;
}
//2.获取符合条件的学生人数
int count =0;
for (int i = 0; i < size; i++) {
if (stus[i].getName().equals(name)) {
count++;
}
}
if (count == 0) {
return null;
}
//3.创建新数组
Student[] newStus = new Student[count];
//4.遍历数据源,把符合条件的学生对象存入新数组中
int index=0;//下标
for (int i = 0; i < size; i++) {
if (stus[i].getName().equals(name)) {
newStus[index++] =stus[i];
}
}
return newStus;
}
@Override
public Student[] getStuBySex(char sex) {
//1.验证学生信息合法性
if (! StuInfoUtil.isSex(sex)) {
return null;
}
//2.获取符合条件的学生人数
int count =0;
for (int i = 0; i < size; i++) {
if (stus[i].getSex() == sex) {
count++;
}
}
if (count == 0) {
return null;
}
//3.创建新数组
Student[] newStus = new Student[count];
//4.遍历数据源,把符合条件的学生对象存入新数组中
int index=0;//下标
for (int i = 0; i < size; i++) {
if (stus[i].getSex() == sex) {
newStus[index++] =stus[i];
}
}
return newStus;
}
@Override
public Student[] getStuAge(int start, int end) {
//1.验证学生信息合法性
if (!StuInfoUtil.isAge(start) || !StuInfoUtil.isAge(end)) {
return null;
}
//2.获取符合条件的学生人数
int count =0;
for (int i = 0; i < size; i++) {
int age=stus[i].getAge();
if (age>=start && age<end) {
count++;
}
}
if (count == 0) {
return null;
}
//3.创建新数组
Student[] newStus = new Student[count];
//4.遍历数据源,把符合条件的学生对象存入新数组中
int index=0;//下标
for (int i = 0; i < size; i++) {
int age=stus[i].getAge();
if (age>=start && age<end) {
newStus[index++] =stus[i];
}
}
return newStus;
}
@Override
public Student[] getStuClassId(String classId) {
//1.验证学生信息合法性
if (! StuInfoUtil.isClassId(classId)) {
return null;
}
//2.获取符合条件的学生人数
int count =0;
for (int i = 0; i < size; i++) {
if (stus[i].getClassId().equals(classId)) {
count++;
}
}
if (count == 0) {
return null;
}
//3.创建新数组
Student[] newStus = new Student[count];
//4.遍历数据源,把符合条件的学生对象存入新数组中
int index=0;//下标
for (int i = 0; i < size; i++) {
if (stus[i].getClassId().equals(classId)) {
newStus[index++] =stus[i];
}
}
return newStus;
}
5.1 编写测试类的查询前端页面
在main包下的Test类中添加以下代码,写一个queryMenu菜单方法
switch (num) {
case 1:
addMenu(scan, sms);
break;
case 2:
deleteMenu(scan, sms);
break;
case 3:
updateMenu(scan, sms);
break;
case 4:
queryMenu(scan, sms);
break;
queryMenu查询菜单方法如下
private static void queryMenu(Scanner scan, StudentManagerSystemImpl sms) {
System.out.println("请选择查询的条件:");
System.out.println("1 - 根据姓名查询");
System.out.println("2 - 根据性别查询");
System.out.println("3 - 根据年龄段查询");
System.out.println("4 - 根据班级号查询");
int num = scan.nextInt();
Student[] stus = null;
switch (num) {
case 1:
System.out.println("请输入需要查询的姓名:");
String name = scan.next();
stus = sms.getStuByName(name);
break;
case 2:
System.out.println("请输入需要查询的性别:");
char sex = scan.next().charAt(0);
stus = sms.getStuBySex(sex);
break;
case 3:
System.out.println("请输入需要查询的起始年龄(包含):");
int start = scan.nextInt();
System.out.println("请输入需要查询的结束年龄(排他):");
int end = scan.nextInt();
stus = sms.getStuAge(start, end);
break;
case 4:
System.out.println("请输入需要查询的班级号:");
String classId = scan.next();
stus = sms.getStuClassId(classId);
break;
}
if(stus != null){
sms.printStus(stus);
}else{
System.out.println("查询错误");
}
}
为了方便打印数组,在StudentManagerSystem接口中,写一个默认方法,在前端Test类中直接调用这个方法
/**
* 打印学生数组
* @param stus目标数组
*/
default void printStus(Student[] stus){
for (Student stu : stus) {
System.out.println(stu);
}
}
6.修改功能
在StudentManagerSystemImpl实现类中,重写修改方法
@Override
public int update(String classId, String id, int type, Object val) {
//1.判断学生信息合法性
if(!StuInfoUtil.isClassId(classId) || !StuInfoUtil.isId(id)){
return -1;
}
//2.判断是否有该学生
int index = query(classId, id);
if (index == -1) {
return -2;//返回-2,就是没有该学生
}
//3.判断修改类型
switch (type) {
case NAME:
String nameVal = (String) val;// name --> 强转成String类型
//判断修改数据的合法性
if(!StuInfoUtil.isName(nameVal)){
return -3;
}
//修改数据
stus[index].setName(nameVal);
break;
case SEX:
char sexVal = (Character) val;// sex --> 强转成Character类型
//判断修改数据的合法性
if(!StuInfoUtil.isSex(sexVal)){
return -3;
}
//修改数据
stus[index].setSex(sexVal);
break;
case AGE:
int ageVal = (Integer) val;
//判断修改数据的合法性
if(!StuInfoUtil.isAge(ageVal)){
return -3;
}
//修改数据
stus[index].setAge(ageVal);
break;
case CLASS_ID:
String classIdVal = (String) val;
//判断目标班级上是否有重复学生
if(query(classIdVal, id) != -1){
return -4;
}
//判断修改数据的合法性
if(!StuInfoUtil.isClassId(classIdVal)){
return -3;
}
//修改数据
stus[index].setClassId(classIdVal);
break;
case ID:
String idVal = (String) val;
//判断目标学号上是否有重复学生
if(query(classId, idVal) != -1){
return -5;
}
//判断修改数据的合法性
if(!StuInfoUtil.isId(idVal)){
return -3;
}
//修改数据
stus[index].setId(idVal);
break;
}
return 1;
}
6.1 编写测试类的修改前端页面
在main包下的Test类中添加以下代码,写一个updateMenu菜单方法
case 3:
updateMenu(scan, sms);
break;
修改菜单
private static void updateMenu(Scanner scan, StudentManagerSystemImpl sms) {
System.out.println("请输入要修改学生的班级号:");
String classId = scan.next();
System.out.println("请输入要修改学生的学号:");
String id = scan.next();
System.out.println("请选择需要修改的类型:");
System.out.println("1 - 修改姓名");
System.out.println("2 - 修改性别");
System.out.println("3 - 修改年龄");
System.out.println("4 - 修改班级号");
System.out.println("5 - 修改学号");
int type = scan.nextInt();
System.out.println("请输入修改的值:");
Object val = null;
switch (type) {
case 1:case 4:case 5:
val = scan.next();//这是多态,向上转型: String -> Object
break;
case 2:
val = scan.next().charAt(0);//char -> Character -> Object
break;
case 3:
val = scan.nextInt();//int -> Integer -> Object
break;
default:
System.out.println("修改失败 -- 修改类型错误");
return;//结束该方法
}
//判断返回值,然后打印错误信息
int updateCode = sms.update(classId, id, type, val);
if(updateCode == -1){
System.out.println("修改失败 -- 学生信息不合法");
}else if(updateCode == -2){
System.out.println("修改失败 -- 没有该学生");
}else if(updateCode == -3){
System.out.println("修改失败 -- 修改值的信息不合法");
}else if(updateCode == -4){
System.out.println("修改失败 -- 目标班级上有学生");
}else if(updateCode == -5){
System.out.println("修改失败 -- 目标学生上有学生");
}else if(updateCode == 1){
System.out.println("修改成功");
}
}