实战项目——用Java实现图书管理系统
前言
首先既然是管理系统,那咱们就要实现以下这几个功能了-->


分析
1.首先是用户分为两种,一个是管理员,另一个是普通用户,既如此,可以定义一个用户类(user),在定义管理员类,普通用户类去继承。
2.还有就是书这个对象,首先是书的属性(书名,作者,价格,种类,是否借出),这可以定义成一个Book类,其实就是存储这些新的容器-- 书架类(Booklist)
3.最后这些功能,仔细观察,由于身份不同,操作也不同,一般来讲,我们可以把对应的方法放到对应的类当中去,但这次用接口也可以巧妙实现
分模块进行编码
book包
为了方便查看,就把这两个类放进一个book的包里。

Book类
package book;public class Book {private String name;//姓名private String author;//作者private int price;//价格private String type;//类型private boolean isLead;//是否被借出public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public int getPrice() {return price;}public void setPrice(int price) {this.price = price;}public String getType() {return type;}public void setType(String type) {this.type = type;}public boolean isLead() {return isLead;}public void setLead(boolean lead) {isLead = lead;}public Book(String name, String author, int price, String type) {this.name = name;this.author = author;this.price = price;this.type = type;}@Overridepublic String toString() {return "book{" +"name='" + name + '\'' +", author='" + author + '\'' +", price=" + price +", type='" + type + '\'' +(isLead==true ? "已借出":" 未借出")+//", isLead=" + isLead +'}';}
}
在这个类中,把书的属性成员定义为私有,通过公共成员函数去访问和调用,最后重写toString 方法来表示输出。
Booklist类
package book;public class Booklist {private Book[] books =new Book[10];private int usedSize;//记录存放次数public Booklist() {books[0]=new Book("红楼梦","曹雪芹",25,"小说");books[1]=new Book("月华","小明",27,"小说");books[2]=new Book("多少","小花",20,"小说");this.usedSize=3;}public boolean isFull(){//判断书架是否满if(this.usedSize==books.length){return true;}else{return false;}}public int getUsedSize() {//获取存了多少本书return usedSize;}//设定书的数量public void setUsedSize(int usedSize) {this.usedSize = usedSize;}public Book getBooks(int pos) {//获取书架中pos位置书的信息return books[pos];}//把新增的图书信息放到pos位置上去public void setBooks(int pos,Book book) {books[pos]=book;}}
在这个书架类中,定义一个容量为10的对象数组来存储书的信息,事先存入三本书,同时usedSize 用来记录书的数量,而后面的方法则与实现对应的功能相关。且往后细看~接口类
package operater;import book.Booklist;public interface IOperation {void work(Booklist booklist);
}
在这个接口里定义了一个方法 work,该方法需要一个 Booklist 对象作为参数。任何实现 IOperation 接口的类都必须提供 work 方法的具体实现。这样一来就方便不同的用户进行操作了。
User包

user类
package User;import book.Booklist;
import operater.IOperation;// 定义一个抽象类 user,表示用户
public abstract class user {protected String name;// 构造方法,初始化用户名称public user(String name) {this.name = name;}//抽象方法,显示菜单并返回用户选择的操作编号public abstract int menu();//存储用户可以执行的操作数组protected IOperation[] iOperations;//根据用户选择执行相应的操作public void DoIoperation(int choice, Booklist booklist) {//调用用户选择的操作的 work 方法this.iOperations[choice].work(booklist);}
}
因为身份不同,所以显示的菜单也不同,所以便声明一个抽象方法 menu(),同时定义一个操作数组,来进行对应的操作,如图

普通用户类(Normaluser)
package User;import operater.*;import java.util.Scanner;public class Normaluser extends user{//重写构造方法public Normaluser(String name) {super(name);//根据不同的输入进行对应的操作,已经方法按顺序放入数组,所以位置别搞错了this.iOperations=new IOperation[]{new Exit(),new Find(),new Borrow(),new Return()};}public int menu(){System.out.println("******普通用户菜单*****");System.out.println("******1.查找图书******** ");System.out.println("******2.借阅图书******** ");System.out.println("******3.归还图书******** ");System.out.println("******0.退出系统******** ");System.out.println("请输入你的操作:");Scanner scanner=new Scanner(System.in);int choice=scanner.nextInt();return choice;}
}
管理员类(Adminuser)
package User;import operater.*;import java.util.Scanner;public class Adminuser extends user{public Adminuser(String name) {super(name);this.iOperations=new IOperation[]{new Exit(),new Find(),new Add(),new Del(),new Show()};}public int menu(){System.out.println("******管理员菜单********");System.out.println("******1.查找图书******** ");System.out.println("******2.新增图书******** ");System.out.println("******3.删除图书******** ");System.out.println("******4.显示图书******** ");System.out.println("******0.退出系统********");System.out.println("************************");System.out.println("请输入你的操作:");Scanner scanner=new Scanner(System.in);int choice=scanner.nextInt();return choice;}}
operater包

Add类
package operater;import book.Book;
import book.Booklist;import java.util.Scanner;public class Add implements IOperation{public void work(Booklist booklist1){if(booklist1.isFull()){System.out.println("书架已满,不能新增!");}System.out.println("新增图书");System.out.println("请输入你要新增的图书的书名:");Scanner scanner=new Scanner(System.in);String bookName=scanner.nextLine();System.out.println("请输入你要新增的图书的作者:");String bookAuthor= scanner.nextLine();System.out.println("请输入你要新增的图书的价格:");int bookPrice = scanner.nextInt();scanner.nextLine();System.out.println("请输入你要新增的图书的类型:");String bookType = scanner.nextLine();Book book=new Book(bookName,bookAuthor,bookPrice,bookType);int currentSize=booklist1.getUsedSize();//新增图书的位置其实就是i本书的位置booklist1.setBooks(currentSize,book);booklist1.setUsedSize(currentSize+1);//书的数量+1System.out.println("成功添加图书");}
}
在新增图书的过程中,要分别添加书的属性才行,这时切不可直接用booklist,这时类对象,不是数组,创建一个对象数组book,之前Booklist中方法便派上用场, 看图就更好理解了~

Borrow类
package operater;import book.Book;
import book.Booklist;import java.util.Scanner;public class Borrow implements IOperation{public void work(Booklist booklist1){System.out.println("借阅图书");System.out.println("请输入你要借阅的书名:");Scanner scanner=new Scanner(System.in);String bookName=scanner.nextLine();//找到要借阅的书的下标for (int i=0; i < booklist1.getUsedSize() ; i++) {Book book1=booklist1.getBooks(i);if(book1.getName().equals(bookName)) {book1.setLead(true);System.out.println("借阅成功!");return;}}System.out.println("借阅失败!");}}
借阅图书其实和删除差不多,只要改变状态为已借出。
Del类
package operater;import book.Book;
import book.Booklist;import java.util.Scanner;public class Del implements IOperation{public void work(Booklist booklist1){System.out.println("删除图书");System.out.println("请输入你要删除的书名:");Scanner scanner=new Scanner(System.in);String bookName=scanner.nextLine();int current=booklist1.getUsedSize();int pos=-1;int i = 0;//找到要删除的书的下标for (; i < current ; i++) {Book book1=booklist1.getBooks(i);if(bookName.equals(book1.getName())) {//System.out.println("找到了");pos=i;}}if(pos>=current){System.out.println("没有你要找的书!");}//开始删除for (int j = pos; j <current-1; j++) {// booklist1[j]=booklist1[j+1];不能直接用类对象Book book= booklist1.getBooks(j+1);booklist1.setBooks(j,book);}booklist1.setUsedSize(current-1);booklist1.setBooks(current-1,null);System.out.println("删除成功!");}
}
删除图书,首先要找到要删除图书的下标pos, 找到后要把后面的图书全都往前移动一格,从pos位置开始遍历,将j+1位置的图书存放到book对象中去,在调用setBook方法传给j位置。后面的位置设置成null,同时更新书的数量~

Exit类
package operater;import book.Booklist;public class Exit implements IOperation{public void work(Booklist booklist1){System.out.println("退出系统");//避免退出系统后内存被回收int current=booklist1.getUsedSize();for (int i = 0; i < current ; i++) {booklist1.setBooks(i,null);}System.exit(0);}
}
直接调用系统的退出即可~
Find类
package operater;import book.Book;
import book.Booklist;import java.util.Scanner;public class Find implements IOperation{public void work(Booklist booklist1){System.out.println("查找图书");System.out.println("请输入你要查找的书名:");Scanner scanner=new Scanner(System.in);String bookName=scanner.nextLine();int current=booklist1.getUsedSize();for (int i = 0; i < current ; i++) {Book book1=booklist1.getBooks(i);if(bookName.equals(book1.getName())) {System.out.println("找到了");System.out.println(book1);return;}}System.out.println("没找到这本书!");}
}
Return类
package operater;import book.Book;
import book.Booklist;
import java.util.Scanner;public class Return implements IOperation{public void work(Booklist booklist1){System.out.println("归还图书....");System.out.println("请输入你要归还的书名:");Scanner scanner=new Scanner(System.in);String bookName=scanner.nextLine();//找到要归还的书的下标for (int i=0; i < booklist1.getUsedSize() ; i++) {Book book1=booklist1.getBooks(i);if(book1.getName().equals(bookName)) {book1.setLead(false);System.out.println("归还成功!");return;}}System.out.println("归还失败!");}}
Show类
package operater;import book.Book;
import book.Booklist;public class Show implements IOperation{public void work(Booklist booklist1){System.out.println("展示图书");int current=booklist1.getUsedSize();for (int i = 0; i < current ; i++) {Book book1=booklist1.getBooks(i);System.out.println(book1);}}
}
这三个其实是大同小异的,都是循环遍历再进行对应的操作,这里主要记住的是String类型的数据比较不能直接用==,而是要用equals()方法。

看到最后,如果觉得文章写得还不错,希望可以给我点个小小的赞,您的支持是我更新的最大动力

相关文章:
实战项目——用Java实现图书管理系统
前言 首先既然是管理系统,那咱们就要实现以下这几个功能了--> 分析 1.首先是用户分为两种,一个是管理员,另一个是普通用户,既如此,可以定义一个用户类(user),在定义管理员类&am…...
利用DeepFlow解决APISIX故障诊断中的方向偏差问题
概要:随着APISIX作为IT应用系统入口的普及,其故障定位能力的不足导致了在业务故障诊断中,APISIX常常成为首要的“嫌疑对象”。这不仅导致了“兴师动众”式的资源投入,还可能使诊断方向“背道而驰”,从而导致业务故障“…...
sqlalchemy获取数据条数
1、sqlalchemy获取数据条数 在SQLAlchemy中,你可以使用count()函数来获取数据表中的记录条数。 from sqlalchemy import create_engine, MetaData, Table# 数据库连接字符串 DATABASE_URI = dialect+driver://username:password@host:port/database# 创建引擎 engine = crea…...
SpringBoot的自动配置核心原理及拓展点
Spring Boot 的核心原理几个关键点 约定优于配置: Spring Boot 遵循约定优于配置的理念,通过预定义的约定,大大简化了 Spring 应用程序的配置和部署。例如,它自动配置了许多常见的开发任务(如数据库连接、Web 服务器配…...
用随机森林算法进行的一次故障预测
本案例将带大家使用一份开源的S.M.A.R.T.数据集和机器学习中的随机森林算法,来训练一个硬盘故障预测模型,并测试效果。 实验目标 掌握使用机器学习方法训练模型的基本流程;掌握使用pandas做数据分析的基本方法;掌握使用scikit-l…...
24位DAC转换的FPGA设计及将其封装成自定义IP核的方法
在vivado设计中,为了方便的使用Block Desgin进行设计,可以使用vivado软件把自己编写的代码封装成IP核,封装后的IP核和原来的代码具有相同的功能。本文以实现24位DA转换(含并串转换,使用的数模转换器为CL4660)为例,介绍VIVADO封装IP核的方法及调用方法,以及DAC转换的详细…...
【大模型LLM面试合集】大语言模型基础_llm概念
1.llm概念 1.目前 主流的开源模型体系 有哪些? 目前主流的开源LLM(语言模型)模型体系包括以下几个: GPT(Generative Pre-trained Transformer)系列:由OpenAI发布的一系列基于Transformer架构…...
Qt时间日期处理与定时器使用总结
一、日期时间数据 1.QTime 用于存储和操作时间数据的类,其中包括小时(h)、分钟(m)、秒(s)、毫秒(ms)。函数定义如下: //注:秒(s)和毫秒(ms)有默认值0 QTime::QTime(int h, int m, int s 0, int ms 0) 若无须初始化时间数据,可…...
数据结构——Hash Map
1. Hash Map简介 Hash Map是一种基于键值对的数据结构,通过散列函数将键映射到存储位置,实现快速的数据查找和存储。它可以在常数时间内完成查找、插入和删除操作,因此在需要频繁进行这些操作时非常高效。 2. Hash Map的定义 散列表ÿ…...
剪画小程序:视频剪辑-视频播放倍数的调整与应用
在这个快节奏的时代,时间变得越来越宝贵,而视频倍数播放功能就像是我们的时间管理小助手,为我们的视频观看带来了极大的便利。你是否好奇它到底能在哪些地方发挥作用呢?让我们一起来看看! 只要使用小程序【剪画】的里…...
使用 Java Swing 和 XChart 创建多种图表
在现代应用程序开发中,数据可视化是一个关键部分。本文将介绍如何使用 Java Swing 和 XChart 库创建各种类型的图表。XChart 是一个轻量级的图表库,支持多种类型的图表,非常适合在 Java 应用中进行快速的图表绘制。 1、环境配置 在开始之前&…...
信息系统运维管理:实践与发展
信息系统运维管理:实践与发展 信息系统运维管理在现代企业中扮演着至关重要的角色,确保信息系统的高效、安全和稳定运行。本文结合《信息系统运维管理》文档内容,探讨了服务设计阶段、服务转换阶段、委托系统维护管理三个主要章节࿰…...
html+js+css登录注册界面
拥有向服务器发送登录或注册数据并接收返回数据的功能 点赞关注 界面 源代码 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <title>Login and Registration Form</title> <style> * …...
英伟达(NVIDIA)数据中心GPU介绍
英伟达(NVIDIA)数据中心GPU按性能由高到低排行: 1. NVIDIA H100 架构:Hopper 核心数量:18352 CUDA Cores, 1456 Tensor Cores 显存:80 GB HBM3 峰值性能: 单精度(FP32)…...
Leetcode 3202. Find the Maximum Length of Valid Subsequence II
Leetcode 3202. Find the Maximum Length of Valid Subsequence II 1. 解题思路2. 代码实现 题目链接:3202. Find the Maximum Length of Valid Subsequence II 1. 解题思路 这一题的话是上一题3201. Find the Maximum Length of Valid Subsequence I的升级版&am…...
通过Spring Boot结合实时流媒体技术对考试过程进行实时监控
本章将深入探讨考试系统中常见的复杂技术问题,并提供基于Spring Boot 3.x的解决方案。涵盖屏幕切换检测与防护、接打电话识别处理、行为监控摄像头使用、网络不稳定应对等,每篇文章详细剖析问题并提供实际案例与代码示例,帮助开发者应对挑战&…...
智能扫地机器人避障与防跌落问题解决方案
智能扫地机器人出现避障与防跌落问题时,可以通过以下几种方式来解决: 一、避障问题的解决方案 1.升级避障技术: ① 激光雷达避障:激光雷达通过发射和接收激光信号来判断与障碍物的距离,具有延迟低、效果稳定、准确度…...
德旺训练营称重问题
这是考小学的分治策略,小学的分治策略几乎都是分三组。本着这个策略,我们做看看。 第一次称重: 分三组,16,16,17,拿两个16称,得到A情况,一样重,那么假铜钱在那组17个里面。B情况不…...
数据决策系统详解
文章目录 数据决策系统的核心组成部分:1. **数据收集与整合**:2. **数据处理与分析**:3. **数据可视化**:4. **决策支持**: 数据决策系统的功能:决策类型:数据决策系统对企业的重要性࿱…...
JSON 简述与应用
1. JSON 简述 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,常用于客户端与服务器之间的数据传递。它基于JavaScript对象表示法,但独立于语言,可以被多种编程语言解析和生成。 1.1 特点 轻量级&#…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
【免费数据】2005-2019年我国272个地级市的旅游竞争力多指标数据(33个指标)
旅游业是一个城市的重要产业构成。旅游竞争力是一个城市竞争力的重要构成部分。一个城市的旅游竞争力反映了其在旅游市场竞争中的比较优势。 今日我们分享的是2005-2019年我国272个地级市的旅游竞争力多指标数据!该数据集源自2025年4月发表于《地理学报》的论文成果…...

