学生管理系统

项目

1. 项目目标
1. 一阶段所有知识点融合,学习,复习!!!
2. 学会基本的 CRUD 增删改查
3. 学会基本的 MVC 模型
4. 学会模块化思想,分离思想
5. 插件式编程
6. 使用反射,Stream流。Lambda表达式,方法引用提升代码
2. 学生管理系统功能分析
学生类对应学生信息:
	属性:
		ID ☆ 数据必须有一个针对项目的唯一索引!!!
		name gender age javaScore WebScore dbScore totalScore
	ID ==> 唯一和自动生成!!![重点]

学生数据信息管理类:
	属性:
		通过数组来存储学生对象,方便后期整体管理
	功能:
		1. 增加学生
		2. 删除学生
		3. 修改学生信息
		4. 查询学生信息
		5. 查询所有学生信息
		6. 查询指定条件的学生信息
		7. 排序功能
3. 学生类完成
3.1 包结构分析和类基本定义
com.qfedu.student.entity
	entity ==> 实体类 描述确实存在的数据类型,人类,电脑类....对应包内的所有类都只是作为数据的载体,没有其他功能。
3.2 id 自动生成和自增长实现
分析:
	1. 需要一个变量,用于记录 id 自增加所需数据,id是一个成员变量,每一次创建对象,都需要给予 id 进行赋值操作。赋值操作需要有一个变量来记录数据内容。
	2. 自动生成 ==> 无论通过哪一个构造方法和new关键字一起使用,创建对象,id 都可以自动赋值/生成
	3. 一个学生对象 id 被赋值之后,该 id 数据不可以重复,需要进行累加操作,方便下一次赋值使用,

技术点:
	1. 存储数据的变量数据类型 ==> int
	2. 累加操作 ==> ++ 自增运算符 或者 += 1 代替方式
	3. 变量应该选择是成员变量,局部变量,还是静态成员变量???
	4. 自动生成???

记录 id 数据变量定位选择 
	变量名 count
	持久性
		count需要在整个程序的运行过程中,都要提供数据进行 id 赋值操作。
			1. 考虑整个程序周期以内有效。√ 合适
			2. 针对于当前对象生存期有效。不适合
	共享性
		每一个对象在创建过程中,都要使用用 count 变量的数据内容,进行 id 赋值操作。每一个对象都可以用
			共享性有需求的!!! static 更合适,成员变量不适合
		
	独立性
		对应当前 Student 类而言,count是共享给每一个对象使用,不具备独立特征。
		独立性需要考虑 count 有且只有类内可以使用!!!【private】
	
	成员变量
		不满足持久性和共享性!!!不合适
	局部变量
		啥也不是!!!
	静态成员变量 
		唯一可行方案!!!
		王浩宇 10遍 反射
		段其俊 10遍 反射

自动生成???
	创建对象 id 自动赋值
	不关调用哪一个构造方法,都可以给予 id 成员变量进行赋值操作。
	使用构造代码块解决问题 !!!
package com.qfedu.student.entity;

/**
 * 学生实体类 【核心技术】 id 自增加!!!
 * 
 * @author Anonymous 2022/03/14 10:17
 */
public class Student {
	private int id;
	private String name;
	private int age;
	private char gender;
	private int javaScore;
	private int webScore;
	private int dbScore;
	private int totalScore;

	/**
	 * 用于在创建对象是给予 ID 变量赋值操作,保证学生 id 不重复,同时可以记录 整个程序运行过程中,创建了多少个学生对象。
	 */
	private static int count = 1;

	/**
	 * 可以使用构造代码块给予 id 成员变量赋值操作,不管调用哪一个构造方法,都可以执行构造代码块内容。
	 * 构造代码块内容在程序的编译阶段是直接给到每一个构造方法方法体内容使用。
	 */
	{
		id = count;
		count += 1;
	}

	/**
	 * 无参构造方法
	 */
	public Student() {
	
	}

	/**
	 * 带有参数的构造方法,但是不提供 id ,totalScore 成员变量赋值操作。id需要自动生成,并且根据当前系统要求唯一!!! totalScore
	 * 是根据 Java成绩,web成绩,数据库成绩计算得来
	 * 
	 * @param name      初始化 String name 属性
	 * @param age       初始化 int age 属性
	 * @param gender    初始化 char gender 属性
	 * @param javaScore 初始化 int javaScore 属性
	 * @param webScore  初始化 int webScore 属性
	 * @param dbScore   初始化 int dbScore 属性
	 */
	public Student(String name, int age, char gender, int javaScore, int webScore, int dbScore) {
		this.name = name;
		this.age = age;
		this.gender = gender;
		this.javaScore = javaScore;
		this.webScore = webScore;
		this.dbScore = dbScore;
		// 根据 java 成绩,web 成绩,数据库成绩计算 总分
		totalScore = javaScore + webScore + dbScore;
	}

	public int getId() {
		return id;
	}

	public void setId(int 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 char getGender() {
		return gender;
	}

	public void setGender(char gender) {
		this.gender = gender;
	}

	public int getJavaScore() {
		return javaScore;
	}

	public void setJavaScore(int javaScore) {
		this.javaScore = javaScore;
	}

	public int getWebScore() {
		return webScore;
	}

	public void setWebScore(int webScore) {
		this.webScore = webScore;
	}

	public int getDbScore() {
		return dbScore;
	}

	public void setDbScore(int dbScore) {
		this.dbScore = dbScore;
	}

	public int getTotalScore() {
		return totalScore;
	}

	public void setTotalScore(int totalScore) {
		this.totalScore = totalScore;
	}

}
3.3 测试
测试包:
	com.qfedu.student.test
需要引入第三方测试工具
	org.junit.Test;
package com.qfedu.student.test;

import org.junit.Test;

import com.qfedu.student.entity.Student;

public class SystemTest {
	/*
	 * @Test 注解标记下方方法为一个测试方法!!!可以摆脱 main 方法要求进行单元测试
	 * 在测试过程中,会提示运行时间,错误信息,执行成功与否
	 */
	@Test
	public void test() {
		System.out.println(1111);
	}
	
	@Test
	public void testStudentId() {
		Student stu1 = new Student();
		Student stu2 = new Student();
		Student stu3 = new Student();
		Student stu4 = new Student("张三", 26, '男', 100, 100, 100);
		Student stu5 = new Student("李四", 26, '男', 100, 100, 100);
		Student stu6 = new Student("王五", 26, '男', 100, 100, 100);
	
		System.out.println(stu1.getId());
		System.out.println(stu2.getId());
		System.out.println(stu3.getId());
		System.out.println(stu4.getId());
		System.out.println(stu5.getId());
		System.out.println(stu6.getId());
	}
}
4. 学生管理系统操作相关类实现
4.1 数据管理和构造方法分析
使用数组来管理学生对象:
	数组类型??? 为自定义 Student 类型 要什么,给什么,用什么,拿什么

包名:
	com.qfedu.student.service
/**
* 是否静态:
* 		是
* 			王浩宇 10遍集合
* 			蒋玮豪 10遍反射 集合 字符串
* 		否 对 √
* 			段其俊 10遍反射
* 			耿智广 10遍反射
*/
private Student[] allStudents;
	
构造方法需要创建 StudentService 对象
	一旦程序中创建了 StudentService 对象,就应该可以提供 StudentService 中的 CRUD 操作。意味着 StudentService 底层存储学生对象的 数组应该具备容量用于存储学生信息,完成后期的操作。
	构造方法就应该创建用于存储学生的底层数组空间,并且需要提供有参和无参构造方法、
package com.qfedu.student.service;

import com.qfedu.student.entity.Student;

/**
 * StudentService 学生相关操作方法 服务类
 * 
 * @author Anonymous 2022/03/14 14:40
 */
public class StudentService {
	/**
	* 底层存储学生对象信息的 Student 类型数组
	*/
	private Student[] allStudents;

	/**
	 * 带有名称的常量,用于封装提示数组的最大容量,提升代码的阅读性。
	 */
	private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
	
	/**
	 * 使用无参数构造方法默认的底层数组容量为10
	 */
	private static final int DEFAULT_CAPACITY = 10;
	
	/**
	 * 无参数构造方法,初始化底层存储学生对象的数组容量为 10
	 */
	public StudentService() {
		allStudents = new Student[DEFAULT_CAPACITY];
	}
	
	/**
	 * 用户通过构造方法参数,提供指定的初始化容量,用于明确当前 StudentService 底层
	 * 存储学生对象的数组容量为多少
	 * 
	 * @param initCapacity 用户指定的初始化底层数组容量
	 */
	public StudentService(int initCapacity) {
		/*
		 * 用户提供的 initCapacity 对应数据进行判断是否合法,
		 * initCapacity < 0 不合法!!!
		 * int[] arr = new int[10];
		 * 
		 * arr.length ==> 10 
		 * 数组所需内存空间,除对应数据存储之外,还需要考虑数组本身组成过程中
		 * 所需的必要内容空间,例如 数组的两头边界,数组的容量数据存储所需内容
		 * 需要提供给数组必要的空余空间,用于数组关键性数组和标记的内存占用
		 * 
		 * Integer.MAX_VALUE - 8 
		 */
		if (initCapacity < 0 || initCapacity > MAX_ARRAY_SIZE) {// Integer.MAX_VALUE = 0x7fffffff int 数据类型最大值
			// TODO 异常抛出
		}
		allStudents = new Student[initCapacity];	
	}
	
}
4.2 添加学生功能实现
4.2.1 方法分析
权限修饰符:
	public
是否静态:
	否 因为需要操作 StudentService 底层 allStudents Student 类型数组,该数组 非 static 修饰
返回值类型:
	boolean 添加成功返回 true ,否则返回 false
方法名:
	add
形式参数列表:
	直接给予 Student 类型对象
	(Student student);
4.2.2 方法声明
public boolean add(Student student)
/*
* 尾插法核心:
* 		计数器
* 		int size;
* 	成员变量
* 		王浩宇 20遍 集合 字符串 变量
*  局部变量
*  	蒋玮豪 10遍 反射 集合 字符串
*  静态成员变量
*  	
*/
4.2.3 方法实现
/**                                                              
 * 添加学生对象到 StudentService 对象底层数组中,采用的添加方式为 尾插法                   
 *                                                               
 * @param student Student 类型对象                                   
 * @return 添加成功返回 true,否则返回 false                                
 */                                                              
public boolean add(Student student) {                            
	/*                                                           
	 * 尾插法核心:                                                    
	 * 		计数器                                                  
	 * 		int size;                                            
	 * 		持久性                                                  
	 * 			size 需要在每一次执行 add 方法的时候都要提供对应的计数器功能。             
	 * 				1. 整个程序周期的持久性。static                         
	 * 				2. 跟随对象的持久性。                                 
	 * 		共享性                                                  
	 * 			size 需要共享吗???                                    
	 * 				不需要共享,保证一定范围的独立性                             
	 * 		独立性                                                  
	 * 			size 应该满足是跟随 StudentService 对象存在的,同时保证数据独立,      
	 * 			仅供当前 StudentService 对象使用                         
	 * 	成员变量 √                                                   
	 *  局部变量 ×                                                   
	 *  静态成员变量 ×                                                 
	 *                                                           
	 *  公开还是私有???                                                
	 *  	private                                              
	 */                                                          
	allStudents[size++] = student;                               
	                                                             
	return true;                                                 
}                                                                
4.3 数组容量扩容方法
4.3.1 实际场景分析
教室容量 90 
目前教室学生人数 88
又来了三个新学生 人数来到 88 + 50 ==> 138

找校长考虑教室问题:
	换教室!!!
	新教室容量 100 120 180 500 1W
			135 大约是原本容量的 1.5 倍
	最少需要 138

注意:
	1. 重点数据 考虑扩容一次至少保存当前添加操作可以执行完毕,容量满足当前添加数据需求。
	2. 余量思想,考虑在原本容量之上扩容原本容量的 50%
	
原教室学生需要换到新教室,该过程【浪费时间】
新教室换上原教室的门牌
4.3.2 扩容方法分析
权限修饰符:
	private
		蒋玮豪 20遍字符串,集合,反射
		段其俊	10遍字符串,集合
是否静态:
	是
		张玉玮 10遍字符串,集合,反射
	否 非静态,静态方法无法操作类内非静态成员变量底层 Student 数组
	需要通过数组得到相关数据和学生信息内容
				
返回值类型:
	void
方法名:
	grow
形式参数列表:
	int minCapacity
4.3.3 方法声明
private void grow(int minCapacity)
4.3.4 grow实现
/**                                                   
 * 用于扩容底层存储学生对象数组的方法,需要提供当前扩容所需的最小容量                  
 *                                                    
 * @param minCapacity 最小容量需求                          
 */                                                   
private void grow(int minCapacity) {                  
	System.out.println("grow method running......."); 
	// 1. 得到原数组容量                                     
	int oldCapacity = allStudents.length;             
                                                      
	// 2. 计算新数组容量 新数组容量大约是原数组容量的 1.5 被                
	int newCapacity = oldCapacity + oldCapacity / 2;  
	                                                  
	// 3. 判断新数组容量是否满足最小容量要求                           
	if (newCapacity < minCapacity) {                  
		newCapacity = minCapacity;                    
	}                                                 
	                                                  
	// 4. 判断新数组容量是否超出最大容量限制                           
	if (newCapacity > MAX_ARRAY_SIZE) {               
		// TODO 异常处理                                  
	}                                                 
	                                                  
	// 5. 根据新数组容量创建新的 Student 类型数组                    
	Student[] temp = new Student[newCapacity];        
	                                                  
	// 6. 原数组数据内容移动到新数组中                              
	for (int i = 0; i < oldCapacity; i++) {           
		temp[i] = allStudents[i];                     
	}                                                 
	                                                  
	// 7. allStudents 成员变量保存新数组地址。                    
	allStudents = temp;                               
}                                                     

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qHuQg3SF-1664244253576)(img/01-数组交换地址操作.png)]

4.4 删除指定 id 学生
4.4.1 方法分析
权限修饰符:
	public
是否静态:
	否
返回值类型:
	Student 被删除学生对象
方法名:
	remove
形式参数列表:
	int id
4.4.2 方法申明
public Student remove(int id);
4.4.3 方法实现
/**                                             
 * 根据用户提供的 id 数据,删除对应的学生对象                      
 *                                              
 * @param id 用户指定的学生 id 号                       
 * @return 被删除的学生对象,如果没有对应学生被删除,返回 null         
 */                                             
public Student remove(int id) {                 
	                                            
	int index = indexOf(id);                    
	                                            
	// 3. 判断 index 是否找到对应学生                     
	if (-1 == index) {                          
		return null;                            
	}                                           
                                                
	// 4. 进行删除操作之前,首先保留被删除学生对象数据内容              
	Student temp = allStudents[index];          
	                                            
	// 5. 从删除位置开始,到有效元素结束,移动数组元素,完成删除操作         
	for (int i = index; i < size - 1; i++) {    
		allStudents[i] = allStudents[i + 1];    
	}                                           
	                                            
	// 6. 最后一个有效位置赋值为 null 同时 size - 1          
	allStudents[--size] = null;                 
	                                            
	return temp;                                
}                                               
4.4.4 补充私有化辅助方法 indexOf
/**                                          
 * 私有成员方法,用于提供指定 id 对应学生对象在底层数组中的下标位置        
 *                                           
 * @param id 用户指定的id号                        
 * @return 对应学生的下标位置,如果没有找到返回 -1             
 */                                          
private int indexOf(int id) {                
	// 1. 判断用户给予的 id 数据是否合法                  
	if (id <= 0) {                           
		// TODO 异常处理                         
	}                                        
	                                         
	// 2. 根据 id 找出对应学生在数组中的下标位置。             
	int index = -1;                          
	                                         
	for (int i = 0; i < size; i++) {         
		if (allStudents[i].getId() == id) {  
			index = i;                       
			break;                           
		}                                    
	}                                        
	return index;                            
}                                            
4.5 根据 id 获取对应学生对象
/**                                               
 * 根据用户指定的id号获取对应的学生对象,如果没有找到,返回null              
 *                                                
 * @param id 用户指定的 id 号                           
 * @return 找的学生对象,如果没有对应学生对象,返回 null              
 */                                               
public Student get(int id) {                      
	int index = indexOf(id);                      
	                                              
	return index > -1 ? allStudents[index] : null;
}                                                 

根据 id 获取对应学生对象

/**                                               
 * 根据用户指定的id号获取对应的学生对象,如果没有找到,返回null              
 *                                                
 * @param id 用户指定的 id 号                           
 * @return 找的学生对象,如果没有对应学生对象,返回 null              
 */                                               
public Student get(int id) {                      
	int index = indexOf(id);                      
	                                              
	return index > -1 ? allStudents[index] : null;
}                                                 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员子衿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值