Java基础快速入门:面向对象高级与信息管理系统实战

本文纲要

  1. 案例驱动教学概述
  2. 分类思想
    2.1 代码臃肿与可维护性问题
    2.2 分工协作:专人干专事
    2.3 信息管理系统的类职责划分
    2.4 类之间的交互流程
  3. 分包思想与包的使用
    3.1 包的本质与创建
    3.2 package、import 与全类名访问
    3.3 包使用的注意事项
  4. static 关键字
    4.1 static 的特点
    4.2 static 的内存图解
    4.3 static 的注意事项
    4.4 解决学号重复问题
  5. 信息管理系统实战
    5.1 项目结构
    5.2 环境搭建
    5.3 菜单搭建
    5.4 添加功能实现
    5.5 查询功能实现
    5.6 删除功能实现
    5.7 修改功能实现
    5.8 代码优化
    5.9 老师管理系统实现
  6. 总结

案例驱动学习概述

采用案例驱动的学习方式:先用已掌握的知识点实现一个案例,然后找出案例中存在的重复代码多、业务逻辑耦合紧、可维护性差等问题,再通过新的知识点进行解决。这样能让大家对知识点的应用场景有更深刻的认知。

基础班的学生管理系统将所有增删改查功能写在一个类中,导致阅读困难、维护不便。实际开发中,我们需要将代码进行分类管理,并引入分类思想和分包思想来提升代码的复用性、可读性和维护性。

分类思想

1 ) 代码臃肿与可维护性问题
如果将多个业务功能集中在一个类文件中,代码量会急剧膨胀,阅读和修改都非常痛苦。例如,学生管理系统的添加和修改方法中,键盘录入学生信息并封装为对象的代码完全重复,导致代码臃肿。

2 ) 分工协作:专人干专事
分类思想的核心是分工协作,专人干专事。就像物流公司,刚开始只有一名员工负责客服、发货、仓库管理,业务量增大后,需要招聘新员工,分别负责客服、发货、库管,这样职责清晰,管理方便。

编写代码也一样,我们应该将不同职责的代码划分到不同的类中,每个类只负责自己的事情

3 ) 信息管理系统的类职责划分
在信息管理系统中,结合分类思想,我们设计出以下类:

类名角色比喻职责
Student数据实体封装学生信息(id, name, age, birthday)
StudentDao库管负责访问存储数据的数组或集合,进行增删改查操作
StudentService业务员负责业务逻辑处理,如判断学号是否存在
StudentController客服与用户交互,接收用户需求,采集数据,打印结果

注意:DAO 是 Data Access Object(数据访问对象)的缩写,不要读作“到”。

4 )类之间的交互流程
用户的操作会依次经过 Controller → Service → Dao,最后将结果返回给用户。

例如添加学生:

数组/集合StudentDaoStudentServiceStudentController用户数组/集合StudentDaoStudentServiceStudentController用户我要添加学生请输入学生ID输入ID判断ID是否存在查询数据访问数组返回查询结果返回结果ID不存在,可以继续请输入姓名、年龄、生日输入信息封装为Student对象执行添加操作将对象存入数组写入数组添加成功添加成功提示"添加成功"

这种分层设计,使得每个类职责清晰,便于维护和扩展。

分包思想与包的使用

1 ) 包的本质与创建

如果项目中有很多类文件,全部放在一起不便于管理。包(package) 就是用来对类文件进行分门别类管理的,它在硬盘上就是一个文件夹。

创建包的规范:

  • 使用多级包,用 . 分隔,如 com.wb.edu.info.manager
  • 命名惯例:公司域名倒写,去掉 www,例如 www.wb.com → com.wb
    包名全部小写

在 IDEA 中,右键 src → New → Package,输入 com.wb.edu.info.manager 即可创建多级包。

2 ) package、import 与全类名访问

package 关键字:声明当前类所属的包,必须放在文件的第一条可执行代码之前(注释不算可执行代码)。每个类文件只能有一个 package 声明。

import 关键字:当需要在不同包下访问类时,可以使用 import 导包,然后直接使用类名。
全类名访问:包名 + 类名,如 com.wb.test2.Student stu = new com.wb.test2.Student();。这种方式主要用于解决多个包下存在同名类时的冲突。

示例代码:

// 不同包下的访问方式
package com.wb.test;
 
// 方式一:import导包
import com.wb.test2.Student;
 
public class TestPackage {
    public static void main(String[] args) {
        Student stu = new Student(); // 使用test2包下的Student
 
        // 方式二:全类名访问,区分同名类
        com.wb.test3.Student stu2 = new com.wb.test3.Student();
    }
}

3 ) 包使用的注意事项

package 语句必须是程序的第一条可执行代码(注释可放在前面)
一个 Java 文件中最多只能有一个 package 语句

如果没有写 package,默认表示无包名,但一般不建议这样做
三个关键字的位置顺序:package → import → class

static 关键字

1 ) static 的特点
static 是“静态”的意思,可以修饰成员变量和成员方法。被它修饰的内容具有以下特点:

  1. 被所有对象共享:一个对象修改了静态变量的值,其他对象也会看到变化。
  2. 随着类的加载而加载,优先于对象存在:类加载时静态变量就在内存中初始化了,不用等到创建对象。
  3. 多了一种调用方式:可以通过 类名.静态成员 直接调用,如 Student.school = “网炐学院”;。

2 ) static 的内存图解

堆内存

静态存储区

school = '网炐学院'

stu1对象
name='张三'
age=23

stu2对象
name=null
age=0

静态变量 school 存储在堆内存的静态存储区,只有一份。
所有对象通过指针共享这份数据。

3 ) static 的注意事项
静态方法中只能访问静态成员(变量和方法),不能访问非静态成员,因为静态存在时对象可能还没创建。
非静态方法中既可以访问静态成员,也可以访问非静态成员。
静态方法中没有 this 关键字,因为 this 代表当前对象,而静态方法不依赖于对象。

public class Student {
    String name;
    int age;
    static String school;
 
    public void show() {
        // 非静态方法可以访问静态和非静态成员
        System.out.println(name + " " + age + " " + school);
    }
 
    public static void method() {
        // 静态方法不能访问非静态成员,也不能使用this
        // this.name = "张三"; // 编译错误
        // name = "张三"; // 编译错误
        school = "程序员"; // 正确 
    }
}

4 ) 解决学号重复问题

在添加学生功能中,如果每次调用 addStudent 方法都 new 一个 StudentController,会导致 StudentDao 中的数组对象被多次创建,数据不共享,学号重复判断失效。

解决方案:将 StudentDao 中的数组声明为 static,使其成为所有对象共享的同一份数据。

public class StudentDao {
    private static Student[] stus = new Student[5]; // 静态共享数组
    // ...
}

这样无论创建多少个 Controller 对象,操作的都是同一个数组,学号重复判断就能正常工作了。

信息管理系统实战

1 ) 项目结构

wb-edu-info-manager
└─ src
   └─ com.wb.edu.info.manager
       ├─ domain
       │   ├─ Person.java
       │   ├─ Student.java
       │   └─ Teacher.java
       ├─ dao
       │   ├─ StudentDao.java
       │   └─ TeacherDao.java
       ├─ service
       │   ├─ StudentService.java
       │   └─ TeacherService.java
       ├─ controller
       │   ├─ StudentController.java
       │   └─ TeacherController.java
       └─ entry
           └─ InfoManagerEntry.java

2 ) 环境搭建

创建模块 wb-edu-info-manager
在 src 下按照上述包结构创建包
创建实体类 Student 和 Teacher,都继承自 Person
创建 Dao、Service、Controller 类,并在 entry 包中创建入口类 InfoManagerEntry

3 ) 菜单搭建
主菜单循环显示,用户选择进入学生管理或老师管理,退出时使用 System.exit(0) 结束 JVM
学生管理菜单也类似,退出时使用带标签的 break 返回主菜单。

// 主菜单 
while (true) {
    System.out.println("--------欢迎来到信息管理系统--------");
    System.out.println("请输入您的选择: 1.学生管理  2.老师管理  3.退出");
    String choice = sc.next();
    switch (choice) {
        case "1":
            new StudentController().start(); break;
        case "2":
            new TeacherController().start(); break;
        case "3":
            System.out.println("感谢您的使用");
            System.exit(0); break;
        default:
            System.out.println("您的输入有误, 请重新输入");
    }
}

4 ) 添加功能实现

基本添加流程:

  1. StudentController.addStudent() 接收用户输入的学号、姓名、年龄、生日,封装为 Student 对象,传递给 StudentService.addStudent(stu)
  2. StudentService.addStudent(stu) 将对象传给 StudentDao.addStudent(stu),并返回添加结果
  3. StudentDao.addStudent(stu) 遍历数组找到第一个 null 位置,存入对象,返回 true;若数组已满返回 false

加入学号重复判断:
Controller 中,先接收学号,调用 StudentService.isExists(id) 判断是否存在
如果存在,循环提示重新输入;如果不存在,跳出循环,继续录入其他信息
StudentService.isExists(id) 调用 StudentDao.findAllStudent() 获取数组,遍历比对 id

关键代码:

// Controller 中
public void addStudent() {
    String id;
    while (true) {
        System.out.println("请输入学生id:");
        id = sc.next();
        if (studentService.isExists(id)) {
            System.out.println("学号已被占用, 请重新输入");
        } else {
            break;
        }
    }
    Student stu = inputStudentInfo(id); // 封装对象
    boolean result = studentService.addStudent(stu);
    System.out.println(result ? "添加成功" : "添加失败");
}
 
// Dao 中
public boolean addStudent(Student stu) {
    int index = -1;
    for (int i = 0; i < stus.length; i++) {
        if (stus[i] == null) {
            index = i;
            break;
        }
    }
    if (index == -1) return false;
    stus[index] = stu;
    return true;
}

5 ) 查询功能实现

Controller 调用 studentService.findAllStudent() 得到数组
如果数组为 null(无数据),提示“查无信息”;否则遍历数组,跳过 null 元素,打印学生信息
ServicefindAllStudent() 调用 Dao 获取数组,判断数组中是否有非 null 元素,有则返回数组,否则返回 null

6 ) 删除功能实现

Controller 中先调用 inputStudentId() 方法获取一个存在的学号(循环判断)
调用 studentService.deleteStudentById(id) 执行删除,并提示“删除成功”
Dao 中根据 id 找到索引,将该位置置为 null

// 获取索引的通用方法
public int getIndex(String id) {
    int index = -1;
    for (int i = 0; i < stus.length; i++) {
        Student stu = stus[i];
        if (stu != null && stu.getId().equals(id)) {
            index = i;
            break;
        }
    }
    return index;
}

7 ) 修改功能实现

Controller 获取存在的学号,再录入新信息并封装为 Student 对象。
调用 studentService.updateStudent(updateId, newStu),提示“修改成功”。
Dao 中通过 getIndex 找到索引,用新对象替换旧对象

8 ) 代码优化

抽取重复代码,提高复用性:
inputStudentId():封装“录入学号并判断是否存在”的逻辑,返回一个存在的学号(用于删除、修改)或一个不存在的学号(用于添加,添加逻辑单独处理)
inputStudentInfo(String id):封装录入学生信息并封装成对象的逻辑,返回 Student 对象

// 抽取的方法 
public String inputStudentId() {
    String id;
    while (true) {
        System.out.println("请输入学生id:");
        id = sc.next();
        if (!studentService.isExists(id)) {
            System.out.println("您输入的id不存在, 请重新输入:");
        } else {
            break;
        }
    }
    return id;
}
 
public Student inputStudentInfo(String id) {
    System.out.println("请输入学生姓名:");
    String name = sc.next();
    System.out.println("请输入学生年龄:");
    String age = sc.next();
    System.out.println("请输入学生生日:");
    String birthday = sc.next();
    Student stu = new Student();
    stu.setId(id);
    stu.setName(name);
    stu.setAge(age);
    stu.setBirthday(birthday);
    return stu;
}

9 ) 老师管理系统实现
老师管理系统的实现与学生管理系统完全对称,只需将 Student 相关类替换为 Teacher 即可
包括:

  • 实体类 Teacher
  • TeacherDaoTeacherServiceTeacherController
  • 菜单、增删改查及代码优化方法均与学生管理相同

总结

通过本次实战,我们掌握了以下核心技能:

  • 分类思想:将代码按职责划分到不同类中,实现高内聚低耦合
  • 分包思想:使用包管理类文件,规范项目结构
  • static 关键字:解决数据共享问题,理解其内存模型和注意事项
  • 分层架构:Controller(交互)→ Service(业务)→ Dao(数据访问),职责清晰,便于维护。
  • 代码优化:抽取重复代码,提高复用性

这些思想和方法是 Java 项目开发的基础,在后续学习中多加练习,形成良好的编码习惯
本文结合案例驱动,从问题出发,逐步引入面向对象高级特性,并完成了一个完整的信息管理系统
代码示例已精简至核心逻辑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Wang's Blog

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

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

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

打赏作者

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

抵扣说明:

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

余额充值