学生管理系统(控制台)
自从考研以来,大三大四很少码代码,导致写代码很生疏。学校学的一些框架和现在互联网公司使用的框架基本上脱钩。SSM框架很少使用,现在基本上都是SpringBoot对以往框架的整合,比如SpringBoot与Shiro安全框架的整合,SpringBoot和SSM的整合等等。
暑假在互联网公司实习两个月眼看就要去读研,还是感觉自己的基础不好。大佬们的说的基础好,不仅仅是Java基本的语法,而且底层的实现过程,比如JVM的底层实现,集合的底层实现,JSP的底层实现。(头大。。。。)计算机的技术很实在,会就是会,不会就是不会。
最近发现,慢慢感觉编程的思想特别重要,有时候在思考,什么是编程?我们为什么要编程?怎么培养自己的编程能力?面向对象OOP的编程语言为什么在现在互联网的大领域经久不衰?…… 怎么从功能——>性能——>智能的跨越?
说白了就是为了发现问题,解决问题。更快,更稳定,造福人类社会,推动整个社会发展。
NOW,重点复习基础,做项目总结!做项目!总结!
一. 本项目使用技术如下:
技术很重要,初期主要感觉还是基本思想和代码的实现的熟练度。
实体类的使用,实体类的作用,枚举类的使用
- 接口 A = new 实现类() 和 实现类 B = new 实现类()
- 接口的使用,对接口的理解,接口实现类
- 容器的使用
二. 需求分析
- 遍历所有学生学生信息
- 添加学生信息
- 根据学号查询学生信息
- 根据姓名查询学生信息
- 根据学号删除学生信息
- 根据学号更新学生信息
三. 代码的实现
1. 学生实体类及其实体类的作用是什么:
问题:实体类的作用是什么?
个人理解:
1. 实体类是数据库——后端——前端的数据线桥梁。万物皆对象,程序是对象的集合,他们通过发送消息来告诉彼此需要做的。想要请求一个对象,就必须发送一条消息,通俗的说,就是对象方法的调用请求。
2. 确定的多个数据可以使用枚举类进行枚举,使用枚举的时候直接使用 .equals()方法判断,枚举类名字直接调用枚举类的内容。
3. 编程语言编写程序就是为了解决现实生活中的抽象复杂的问题,通过对某类事务的实例化对象进行操作,具体实现具体的功能。
学生实体类代码:
package com.student.cn;
public class Student {
private int id;
private String name;
private int age;
private Gender gender;
public Student(){}
public Student(int id,String name,int age,Gender gender){
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
}
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 Gender getGender(){
return gender;
}
public void setGender(Gender gender){
this.gender = gender;
}
public String toString(){
return "学生信息:" + "[id:" + id + "name:" + name
+ "age:" + age + "Gender:" + gender;
}
}
enum Gender{
男,女
}
2. 使用接口构建对对象操作的方法可以一目了然的看出对对象有哪些操作,代码如下:
首先复习下接口:
① 接口接口是一系列方法的声明,是一些方法特殊正的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
② 接口可以理解为特殊的类,里面全部是由全局常量和公共抽象方法组成,接口中默认是抽象方法。接口是解决Java无法使用多继承的一种手段,但是接口在实际中更多的作用是指定标准。或者是我们可以直接把接口理解为100%的抽象类,即接口中的方法必须全部是抽象方法。
③ 一个接口也能拥有方法和属性,接口中声明的方法是抽象的,可以不用写public abstract形容,接口中的方法让程序知道能做什么不能做什么,对对象的行为动作功能进行描述。就是描述对象拥有哪一种的能力。
④ 抽象方法只能存在于抽象类和接口中,但是抽象类中却能存在非抽象方法,有方法体的方法,接口是百分之百的抽象类。接口中的常量修饰一定是final进行修饰,在抽象类中可以不适用飞final的成员变量。
⑤ 接口不能够实例化,实例化是在堆空间中开辟一个空间,实现内存中的一块地址,Student s = new Student(),内存中的值就是存放对象的一些属性。比如s中的属性是name和age ,s指向堆内存中的内容,s在栈里面。
⑥ Java的内存区间分为四类:栈,堆,代码区,静态数据。接口为什么不能够被实例化?接口中只允许有静态的属性和方法的声明。静态属性存储在静态区,方法的声明存储在代码区。所以接口不能实例化,实例化只会浪费一块堆区域,接口实例化没有任何意义。
package com.student.cn;
import java.util.List;
public interface IStudent {
//遍历显示所有学生信息,打印出来就可以了,不需要有返回值
void showAll();
//增加学生信息,是增加成功或者是失败?需要判断下
boolean addStudent();
//根据学号查找学生信息,返回的是一个学生信息
Student findStudentById(int id);
//根据学生姓名查找学生信息,可能有学生姓名
List<Student> findStudentByName(String name);
//根据学号删除学生信息,是否删除成功需要判断下
boolean deleteStudent(int id);
//根据学号修改学生信息,是否修改成功
boolean updateStudent(int id);
}
3. 接下来就是接口实现类
首先接口定义了对对象操作的方法,对编码进行更新或者重构系统的时候可以一目了然的看到对象的基本操作,具体方法体的实现在实现类中进行。现在有一个小问题,涉及到多态。当我们对接口声明的时候往往使用多态。
具体我们复习下多态:
① 同种类的不同的对象,有着不同的解释,产生不同的执行结果。简单的说,就是积累引用子类对象。同一个按钮有着不同的处理方式。比如Person person = new Student();那这个父类的 一引用就是子类的对象。Animal a = new Dog();
② 通过父类的引用指向子类的对象。向上转型。引用只能调用父类的属性或者方法。如果父类的方法被子类重写的,执行的是子类重写后的方法。父类和子类有同名的属性名,调用子类的属性。
③ 安全性
向上转型(小类型转换为大类型):Person p = new Student(); 是安全的 ,因为学生本身是一个人。
向下转型(大类型转换为小类型,需要具体的大类型的某一块判断):Dog dog = new Dog() ; Animal animal = dog; Dog dog = (Dog) animal; 向下转型是转型的对象;判断父类所指对象是否属于具体子类对象,if(animal instanceof Dog) 左边的动物类的对象是否为右边狗的实例,是的话则向下转型成功,转换失败会出现类型转换异常ClassCastException,规避风险就是判断是否为本类的对象。
④ 接口实现,抽象类,继承父类进行方法的重写。同一个类中进行方法的重载。
具体实现类代码如下:
在同一个类的方法是方法的重载。在实现类中需要注意的是返回值的类型,需要的是什么?就定义什么。
package com.test.cn;
import java.util.*;
public class StudentOperationImpl implements IStudentOperation{
//需要一个容器来存取,使用键值来存取,键代表id,值代表Student的类的集合
Map<Integer,Student> students = new HashMap();
Scanner scanner = new Scanner(System.in);
//欢迎界面
public void welcome(){
System.out.println("欢迎来到学生信息管理系统");
}
//菜单
public void showMenu(){
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("7.退出");
}
//退出
public void terminal(){
System.out.println("谢谢使用学生信息管理系统");
}
//显示所有学生信息
public void showAll() {
Set<Integer> id = students.keySet();
if (id != null) {
Iterator<Integer> iterator = id.iterator();
while (iterator.hasNext()) {
int sid = iterator.next();
Student stu = students.get(sid);
System.out.println(stu);
}
}else {
System.out.println("学生信息为空!");
}
}
//添加学生信息
public boolean addStudent() {
int id = MyUtil.getIntger(scanner,"请输入学生的学号信息:");
String name = MyUtil.getString(scanner,"请输入学生的姓名:");
int age = MyUtil.getIntger(scanner,"请输入学生的年龄");
Gender gender = MyUtil.getString(scanner,"请输入学生的性别信息").equals("男")?Gender.男:Gender.女;
Student student = new Student(id,name,age,gender);
if (student != null){
System.out.println("添加学生成功!");
students.put(id,student);
return true;
}else {
System.out.println("添加失败!");
return false;
}
}
//通过id查找学生信息
public Student findById(int id) {
Student student = students.get(id);
if (student != null){
System.out.println(student);
}else {
System.out.println("查找的学生不存在!");
}
return student;
}
//重点是获取id,然后再传参数
public Student findById(){
int sid = MyUtil.getIntger(scanner,"请输入查询学生的id");
return findById(sid);
}
//两个方法总有一方需要输出,输出一方
//通过姓名查找学生信息,学生信息可能有重复的,所以使用的是集合
public List<Student> findByName(String name) {
//定义一个容器,存储查询结果
List<Student> list = new ArrayList<>();
//将Map集合里面的Student放到Collection集合里面
Collection<Student> stu = students.values();
//使用迭代器对Collection<>集合迭代
Iterator<Student> iterator = stu.iterator();
while(iterator.hasNext()){
//迭代的是Student来接收
Student s = iterator.next();
if (s.getName().equals(name)){
list.add(s);
}
}
if (list.size() == 0){
return null;
}else {
return list;
}
}
public void findByName(){
String name = MyUtil.getString(scanner, "请输入需要查询的姓名:");
List<Student> list = findByName(name);
if (list == null) {
System.out.println("学生信息不存在!");
} else {
System.out.println("查询学生信息如下:");
Iterator<Student> iterator = list.iterator();
while (iterator.hasNext()) {
Student student = iterator.next();
System.out.println(student);
}
}
}
//通过id更新学生信息
public boolean updateStudent(int id) {
Student stu = students.get(id);
if (stu != null) {
int sid = MyUtil.getIntger(scanner,"请输入更新学生的学号:");
String name = MyUtil.getString(scanner,"请输入更新的学生姓名:");
int age = MyUtil.getIntger(scanner, "请输入更新的学生年龄:");
Gender gender = MyUtil.getString(scanner,"请输入要更新的学生性别:").equals("男")?Gender.男:Gender.女;
stu.setId(sid);
stu.setName(name);
stu.setAge(age);
stu.setGender(gender);
// students.put(sid,stu);
}
return stu == null?false:true;
}
public void updateStudent(){
int id = MyUtil.getIntger(scanner,"请输入你id");
// 看带入参数返回的数据
boolean b = updateStudent(id);
if (b) {
System.out.println("修改成功");
} else {
System.out.println("该学生不存在!");
}
}
//通过id删除学生信息
public boolean deleteStudent(int id) {
//如果键值对存在的话,删除id对应map集合
Student s = students.remove(id);
return s == null?false:true;
}
public void deleteStudent(){
int id = MyUtil.getIntger(scanner, "请输入学生学号");
boolean b = deleteStudent(id);
if (b) {
System.out.println("删除成功!");
} else {
System.out.println("删除失败!");
}
}
}
4. 接下来main方法的测试
立足于发现问题,修改代码需求,解决问题。
请朋友们自己测试,具体代码如下:
package com.test.cn;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
StudentOperationImpl stu = new StudentOperationImpl();
Scanner scanner = new Scanner(System.in);
while (true) {
stu.showMenu();
int count = MyUtil.getIntger(scanner,"请输入你选择的操作:");
switch (count) {
case 1:
stu.showAll();
break;
case 2:
stu.addStudent();
break;
case 3:
stu.findById();
break;
case 4:
stu.findByName();
break;
case 5:
stu.updateStudent();
break;
case 6:
stu.deleteStudent();
break;
case 7:
stu.terminal();
return;
}
}
}
}
5. 项目总结
这个控制台项目很简单,但是真的会反应出自己的具体问题,包括编程思想,逻辑思路,实现过程,心路等。