用 Java 打造学生管理系统 —— 核心功能全实现
做任何项目都要先 “拆解需求、分模块实现”,学生管理系统也不例外:
1. 第一步:定义学生实体类
目的:现实中的 “学生” 是一个实体,有学号、姓名、年龄、班级等属性,在 Java 中需要用类来封装这些属性,这是面向对象中 “封装” 思想的体现。
核心操作:
定义私有成员变量(学号、姓名、年龄等,学号唯一,作为后续增删改查的标识)。
提供公共的getter/setter方法(私有变量不能直接外部访问,通过 get/set 操作属性,保证数据安全性)。
提供有参 / 无参构造方法(方便快速创建学生对象)。
重写toString()方法(默认打印对象地址,重写后可友好展示学生信息)。
2. 第二步:实现核心业务逻辑(增删改查,业务层)
目的:封装所有对学生数据的操作,解耦 “数据操作” 和 “用户交互”,方便后续维护和扩展。
核心准备:使用ArrayList<Student>存储学生对象(相比数组,ArrayList 支持动态扩容,增删操作更便捷,适合新手),并将集合私有化(避免外部直接修改集合,保证数据安全)。
核心功能实现:
增加:先校验学号是否重复(避免数据冗余),不重复则将学生对象添加到集合。
删除:根据学号查找学生,存在则从集合中移除,不存在则提示用户。
修改:根据学号查找学生,存在则更新其姓名 / 年龄等属性,不存在则提示用户。
查询:分为 “查询所有学生” 和 “按学号查询单个学生”,满足不同查询需求。
3. 第三步:实现控制台用户交互(界面交互层)
目的:给用户提供操作入口,接收用户输入,调用业务层的增删改查方法,并将结果反馈给用户。
核心操作:
使用Scanner类接收用户输入(菜单选择、学生信息录入等)。
制作简易菜单(如 “1. 增加 2. 删除 3. 修改 4. 查询 5. 退出”)。
使用循环(while(true))让系统持续运行,直到用户选择退出。
对用户输入进行简单校验(如避免菜单选择输入非数字)。
4. 第四步:编写主程序入口(启动类)
目的:整合所有模块,启动学生管理系统。
核心操作:创建业务层对象和交互层逻辑,运行循环菜单,让系统正常工作。
二、具体代码实现(完整可运行,带详细注释)
下面分 3 个类实现,所有类放在同一个包下即可。
类 1:Student.java(学生实体类,封装数据)
/*学生实体类:封装学生的属性和行为,体现OOP的封装思想
职责:只存储学生数据,不处理业务逻辑*/
public class Student {
// 1. 私有成员变量(学号、姓名、年龄、班级),学号唯一标识学生
private String id; // 学号(用String更灵活,支持如"2026001"格式,避免int长度限制)
private String name; // 姓名
private int age; // 年龄
private String clazz; // 班级(避免和关键字class重名)
// 2. 无参构造方法:方便后续反射、集合扩容等场景使用
public Student() {
}
// 3. 有参构造方法:方便快速创建完整的学生对象
public Student(String id, String name, int age, String clazz) {
this.id = id;
this.name = name;
this.age = age;
this.clazz = clazz;
}
// 4. getter/setter方法:外部访问和修改私有变量的唯一入口,保证数据安全
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
// 5. 重写toString()方法:默认打印对象地址,重写后友好展示学生信息
@Override
public String toString() {
return "学生信息:" +
"学号='" + id + '\'' +
", 姓名='" + name + '\'' +
", 年龄=" + age +
", 班级='" + clazz + '\'';
}
}
类 2:StudentManager.java(业务逻辑类,实现增删改查)
import java.util.ArrayList;
import java.util.List;
/**
* 学生管理业务类:封装所有增删改查逻辑,是系统的核心
* 职责:只处理业务逻辑,不与用户直接交互
*/
public class StudentManager {
// 1. 私有化ArrayList集合,存储学生对象,仅本类可访问,保证数据安全
// 泛型<Student>:限定集合只能存储Student对象,避免类型错误
private List<Student> studentList = new ArrayList<>();
// 功能1:增加学生
public boolean addStudent(Student student) {
// 先校验学号是否重复(核心:避免重复数据)
if (findStudentById(student.getId()) != null) {
// 学号已存在,返回false表示添加失败
return false;
}
// 学号不存在,添加到集合,返回true表示添加成功
studentList.add(student);
return true;
}
// 功能2:删除学生(根据学号)
public boolean deleteStudent(String id) {
// 先查找该学号的学生
Student student = findStudentById(id);
if (student != null) {
// 找到学生,移除出集合,返回true表示删除成功
studentList.remove(student);
return true;
}
// 未找到学生,返回false表示删除失败
return false;
}
// 功能3:修改学生(根据学号,更新其他属性)
public boolean updateStudent(String id, Student newStudent) {
// 先查找该学号的学生
Student oldStudent = findStudentById(id);
if (oldStudent != null) {
// 找到学生,更新姓名、年龄、班级(学号不建议修改,作为唯一标识)
oldStudent.setName(newStudent.getName());
oldStudent.setAge(newStudent.getAge());
oldStudent.setClazz(newStudent.getClazz());
return true;
}
// 未找到学生,返回false表示修改失败
return false;
}
// 功能4:查询单个学生(根据学号)
public Student findStudentById(String id) {
// 遍历集合,查找学号匹配的学生
for (Student student : studentList) {
// 字符串比较用equals(),不能用==(==比较地址,equals比较内容)
if (student.getId().equals(id)) {
// 找到学生,返回该学生对象
return student;
}
}
// 遍历完未找到,返回null
return null;
}
// 功能5:查询所有学生
public List<Student> findAllStudents() {
// 返回集合的拷贝?不,新手直接返回原集合(简化),后续可优化为返回不可变集合
return studentList;
}
// 辅助方法:判断集合是否为空(方便交互层提示用户)
public boolean isStudentListEmpty() {
return studentList.isEmpty();
}
}
类 3:StudentSystem.java(主程序类,实现用户交互 + 启动系统)
import java.util.List;
import java.util.Scanner;
/**
* 学生管理系统主类:实现用户交互,调用业务层方法,是系统的入口
* 职责:只处理用户交互,不处理核心业务逻辑
*/
public class StudentSystem {
// 1. 创建Scanner对象,接收用户输入(全局使用,避免重复创建)
private static Scanner scanner = new Scanner(System.in);
// 2. 创建业务层对象,调用增删改查方法
private static StudentManager studentManager = new StudentManager();
public static void main(String[] args) {
// 系统启动入口,循环展示菜单
System.out.println("===== 学生管理系统启动 =====");
while (true) {
// 打印菜单
showMenu();
// 接收用户菜单选择
String choice = scanner.next();
// 分支判断,执行对应功能
switch (choice) {
case "1":
addStudentUI();
break;
case "2":
deleteStudentUI();
break;
case "3":
updateStudentUI();
break;
case "4":
findAllStudentsUI();
break;
case "5":
System.out.println("===== 退出学生管理系统,感谢使用 =====");
// 关闭Scanner,退出程序
scanner.close();
System.exit(0);
break;
default:
System.out.println("输入错误,请选择1-5之间的选项!");
}
}
}
// 辅助方法:展示菜单
private static void showMenu() {
System.out.println("\n===== 学生管理系统菜单 =====");
System.out.println("1. 增加学生");
System.out.println("2. 删除学生");
System.out.println("3. 修改学生");
System.out.println("4. 查询所有学生");
System.out.println("5. 退出系统");
System.out.println("============================");
System.out.print("请输入你的选择:");
}
// 交互功能1:增加学生的界面逻辑
private static void addStudentUI() {
System.out.println("\n===== 增加学生 =====");
// 接收学生信息
System.out.print("请输入学生学号:");
String id = scanner.next();
System.out.print("请输入学生姓名:");
String name = scanner.next();
System.out.print("请输入学生年龄:");
int age = scanner.nextInt();
scanner.nextLine(); // 吸收换行符,避免后续输入异常
System.out.print("请输入学生班级:");
String clazz = scanner.nextLine();
// 创建学生对象
Student student = new Student(id, name, age, clazz);
// 调用业务层增加方法
boolean result = studentManager.addStudent(student);
// 反馈结果给用户
if (result) {
System.out.println("增加学生成功!");
} else {
System.out.println("该学号已存在,增加学生失败!");
}
}
// 交互功能2:删除学生的界面逻辑
private static void deleteStudentUI() {
System.out.println("\n===== 删除学生 =====");
// 先判断集合是否为空
if (studentManager.isStudentListEmpty()) {
System.out.println("当前无学生数据,无法删除!");
return;
}
// 接收学号
System.out.print("请输入要删除的学生学号:");
String id = scanner.next();
// 调用业务层删除方法
boolean result = studentManager.deleteStudent(id);
// 反馈结果
if (result) {
System.out.println("删除学生成功!");
} else {
System.out.println("该学号不存在,删除学生失败!");
}
}
// 交互功能3:修改学生的界面逻辑
private static void updateStudentUI() {
System.out.println("\n===== 修改学生 =====");
// 先判断集合是否为空
if (studentManager.isStudentListEmpty()) {
System.out.println("当前无学生数据,无法修改!");
return;
}
// 接收要修改的学号
System.out.print("请输入要修改的学生学号:");
String id = scanner.next();
// 接收新的学生信息
System.out.print("请输入新的学生姓名:");
String newName = scanner.next();
System.out.print("请输入新的学生年龄:");
int newAge = scanner.nextInt();
scanner.nextLine(); // 吸收换行符
System.out.print("请输入新的学生班级:");
String newClazz = scanner.nextLine();
// 创建新的学生对象(存储新属性)
Student newStudent = new Student(id, newName, newAge, newClazz);
// 调用业务层修改方法
boolean result = studentManager.updateStudent(id, newStudent);
// 反馈结果
if (result) {
System.out.println("修改学生成功!");
} else {
System.out.println("该学号不存在,修改学生失败!");
}
}
// 交互功能4:查询所有学生的界面逻辑
private static void findAllStudentsUI() {
System.out.println("\n===== 查询所有学生 =====");
// 先判断集合是否为空
if (studentManager.isStudentListEmpty()) {
System.out.println("当前无学生数据!");
return;
}
// 调用业务层查询所有方法,获取学生列表
List<Student> studentList = studentManager.findAllStudents();
// 遍历打印所有学生信息
for (Student student : studentList) {
// 直接打印student,会调用重写后的toString()方法
System.out.println(student);
}
System.out.println("===== 查询完成,共" + studentList.size() + "名学生 =====");
}
}
三、为什么要这么做?
为什么用String存储学号,而不是int?
学号可能包含前缀(如 “2026-001”)、或长度超过int范围(int最大为 2147483647),String更灵活,能满足更多场景需求。
为什么要校验学号唯一性?
学号是学生的唯一标识,重复的学号会导致后续修改、删除时无法准确找到目标学生,造成数据混乱,这是实际项目中 “数据唯一性” 的基础要求。
为什么字符串比较用equals(),而不是==?
==比较的是对象的内存地址,两个不同的String对象即使内容相同,地址也不同;equals()比较的是字符串的实际内容,符合学号比较的需求。
为什么要将ArrayList私有化?
体现 “封装” 思想,避免外部类直接修改集合(如直接调用clear()清空所有数据),保证数据安全,所有对集合的操作都必须通过业务层提供的方法进行,便于控制和维护。
为什么要重写toString()方法?
默认情况下,打印对象会输出 “类名 @哈希值”(如Student@1b6d3586),无法直观展示学生信息,重写后可以友好地打印学生的所有属性,方便调试和用户查看。
四、注意事项
输入数据合法性校验:
上述代码未处理 “年龄输入非数字” 的情况(如用户输入 “abc” 作为年龄,会抛出InputMismatchException),新手后续可通过try-catch捕获异常,提升程序健壮性。
可增加 “姓名不能为空”“年龄必须大于 0” 等校验,避免无效数据录入。
数据持久化问题:
上述系统的数据存储在内存中,程序退出后数据会丢失,新手后续可学习IO流(将数据写入文件)或JDBC(将数据存入数据库,如 MySQL),实现数据永久保存。
代码规范性:
类名、方法名遵循 Java 驼峰命名法(类名首字母大写,方法名首字母小写),如StudentManager、addStudent。
适当添加注释,尤其是核心业务逻辑,方便自己后续阅读和他人协作。
避免重复创建对象:
Scanner和StudentManager对象在主类中全局创建一次即可,避免在每个方法中重复创建,浪费内存资源。
菜单循环的退出逻辑:
使用System.exit(0)正常退出程序,避免无限循环无法终止,同时关闭Scanner资源,避免资源泄露。
五、做学生管理系统可以培养项目思维和逻辑思维:
学会将 “学生管理系统” 这个复杂需求拆解为 “实体类”“业务层”“交互层” 等简单模块,逐步实现,培养 “分而治之” 的项目开发思维,为后续开发复杂项目铺路。
更多推荐


所有评论(0)