【JavaSE】基础笔记 - 图书管理系统(保姆教程,含源码)

news2025/1/11 0:42:50

 

目录

1、图书管理系统介绍

2、大致框架

3、代码实现步骤

3.1、Book图书类

3.2、BookList书架类

3.3、User用户类、AdminUser类、NormalUser类

3.4、IOperation操作接口

3.5、继承IOperation接口的操作类

3.6、完善User类

3.7、Mian类 

4、完整代码

 

Java的三大特性是:封装、继承和多态。最近博主刚刚学完Java的三大特性,因此想写一个小项目巩固一下知识点。

这次的简单图书管理系统主要是为了练习继承,接口和多态的使用,那么就用这篇博客来讲解一下这个小项目,目的只是为了练习。

1、图书管理系统介绍

首先运行系统,需要先输入用户名称,接着选择身份(管理员/普通用户),如果是管理员,则打印管理员菜单,如果是普通用户则打印普通用户菜单,并等待接收执行指令编号,通过输入不同指令编号调用不同方法。

2、大致框架

图书管理系统,图书是一定需要的,要创建一个图书类,包括图书的书名、作者名、书的单价、书的类型、是否借出图书。用户也是一定需要的,所以要创建一个用户类。现在为了增加难度,我想要设置两个用户类:一个是管理员类,可以让管理员对图书进行管理,管理员对图书进行增删查改;一个就是普通的用户类,借阅归还图书。同时,两个类对应的菜单是不相同的。其他的内容就在写代码的时候在进行补充。

 

3、代码实现步骤

3.1、Book图书类

简单的对Book进行描述,并生成对应的get和set方法。然后重写继承于Object类的toSring()方法,方便后续打印图书内容。

package book;

public class Book {
    private String name;  //书名
    private String author;
    private int price;
    private String type;
    private boolean isBorrowed; //是否被借出   成员变量默认值false

    public Book() {
    }

    public Book(String name, String author,
                int price, String type) {
        this.name = name;
        this.author = author;
        this.price = price;
        this.type = type;
    }

    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 isBorrowed() {
        return isBorrowed;
    }

    public void setBorrowed(boolean borrowed) {
        isBorrowed = borrowed;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                ", type='" + type + '\'' +
                ", isBorrowed=" + isBorrowed +
                '}';
    }
}

3.2、BookList书架类

书架类中包含了一个成员变量books,一个用于记录当前书架放了几本书的usedSize。

然后对BookList的空参构造函数进行编写:给books分配空间,这里设置固定大小10。接着初始化三个图书信息,用于表示当前书架中存在的图书。

写上对应的get和set方法,其中getBook方法是通过传入的下标得到指定的book,setBook是通过传入的下标和book,在对应下标处存入book。

package book;

public class BookList {
    private Book[] books;
    private int usedSize;//记录当前书架放了几本书

    public BookList() {
        this.books = new Book[10];
        this.books[0] = new Book("三国演义","罗贯中",10,"小说");
        this.books[1] = new Book("西游记","吴承恩",9,"小说");
        this.books[2] = new Book("红楼梦","曹雪芹",19,"小说");
        this.usedSize = 3;
    }

    public int getUsedSize() {
        return usedSize;
    }

    public void setUsedSize(int usedSize) {
        this.usedSize = usedSize;
    }

    public Book getBook(int pos) {
        return books[pos];
    }

    public void setBook(Book book, int pos) {
        books[pos] = book;
    }
}

3.3、User用户类、AdminUser类、NormalUser类

User  

为了实现向上转型和多态,这里使用首先创建一个Uesr类,用于被AdminUser类和NormalUser类继承。

在User类中定义成员变量name,表示用户名。因为不同的身份打印的菜单是不一致的,因此User类中的menu()菜单方法写成抽象方法,在后面子类继承时再进行实现。

package user;

import book.BookList;
import operation.IOperation;

public abstract class User {
    protected String name;

    public User(String name) {
        this.name = name;
    }
    public abstract int menu();   //抽象方法

}

  NormalUser 

NormalUser类继承User类并重写menu()方法。

package user;

import operation.*;

import java.util.Scanner;

public class NormalUser extends User{
    public NormalUser(String name) {
        super(name);
    }

    @Override
    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("===========================");
        System.out.println("请输入你的操作:");
        Scanner sc = new Scanner(System.in);
        int choice = sc.nextInt();
        return choice;
    }
}

 AdminUser 

AdminUser类继承User类并重写menu()方法。

package user;

import operation.*;

import java.util.Scanner;

public class AdminUser extends User{
    public AdminUser(String name) {
        super(name);
    }

    @Override
    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 sc = new Scanner(System.in);
        int choice = sc.nextInt();
        return choice;

    }
}

3.4、IOperation操作接口

这里定义接口的目的是为了能够使后续创建的操作类能够被同一个对象接收,而只要这些操作类都实现了同一接口,就能够被统一接收,实现向上转型

package operation;

import book.BookList;

public interface IOperation {
    void work(BookList bookList);
}

3.5、继承IOperation接口的操作类

根据管理员和普通用户的菜单,操作类可以分为以下的七个

  1. 新增图书AddOperation
  2. 借阅图书BorrowOperation
  3. 删除图书DelOperation
  4. 查找图书FindOperation
  5. 显示图书ShowOperation
  6. 归还图书ReturnOperation
  7. 退出系统ExitOperation

 AddOperation

package operation;

import book.Book;
import book.BookList;

import java.util.Scanner;

public class AddOperation implements IOperation{
    @Override
    public void work(BookList bookList) {
        Scanner sc = new Scanner(System.in);
        System.out.println("新增图书!");
        System.out.println("请输入你要新增图书的书名:");
        String name = sc.nextLine();
        System.out.println("请输入你要新增图书的作者:");
        String author = sc.nextLine();
        System.out.println("请输入你要新增图书的价格:");
        int price = sc.nextInt();
        sc.nextLine();  //接收回车,sc.nextInt()不会读掉回车,所以需要先接收回车再进行。或者调换一下位置
        System.out.println("请输入你要新增图书的类型:");  //nextInt和nextLine会存在冲突
        String type = sc.nextLine();
        Book book = new Book(name,author,price,type);
        int currentSize = bookList.getUsedSize();

        for (int i = 0; i < currentSize; i++) {
            Book tmp = bookList.getBook(i);
            if(tmp.getName().equals(name)) {
                System.out.println("存在这本书,不能重复添加!");
                return;
            }
        }

        bookList.setBook(book,currentSize);
        bookList.setUsedSize(currentSize+1);
    }
}

BorrowOperation

package operation;

import book.Book;
import book.BookList;

import java.util.Scanner;

public class BorrowOperation implements IOperation {
    @Override
    public void work(BookList bookList) {
        System.out.println("借阅图书!");
        Scanner sc = new Scanner(System.in);
        System.out.println("请写出你要借阅图书的书名:");
        String name = sc.nextLine();

        int currentSize = bookList.getUsedSize();

        for (int i = 0; i < currentSize; i++) {
            Book book = bookList.getBook(i);
            if (book.getName().equals(name)) {
                book.setBorrowed(true);
                System.out.println("借阅成功!");
                return;
            }
        }
        System.out.println("没有书名为'" + name + "'的书籍");
    }
}

DelOperation

package operation;

import book.Book;
import book.BookList;

import java.util.Scanner;

public class DelOperation implements IOperation {
    @Override
    public void work(BookList bookList) {
        Scanner sc = new Scanner(System.in);
        System.out.println("删除图书!");
        System.out.println("请写出你要删除图书的书名:");
        String name = sc.nextLine();
        int currentSize = bookList.getUsedSize();
        int index = -1;
        int i = 0;
        for (; i < currentSize; i++) {
            if (bookList.getBook(i).getName().equals(name)) {
                index = i;
                break;
            }
        }
        if (i > currentSize) {
            System.out.println("不存在书名为'" + name + "'的书籍,无法删除!");
            return;
        }
        //使用移动覆盖作为删除
        for (int j = index; j < currentSize - 1; j++) {
            Book book = bookList.getBook(j + 1);
            bookList.setBook(book, j);
        }
        //方便系统自动回收
        bookList.setBook(null, currentSize - 1);
        bookList.setUsedSize(currentSize - 1);
        System.out.println("成功删除书名为'" + name + "'的书籍!");
    }
}

FindOperation

package operation;

import book.Book;
import book.BookList;

import java.util.Scanner;

public class FindOperation implements IOperation{
    @Override
    public void work(BookList bookList) {
        System.out.println("查找图书!");
        System.out.println("请写出你要查找的图书的书名:");
        Scanner sc = new Scanner(System.in);
        String name = sc.nextLine();

        int currentSize = bookList.getUsedSize();
        for (int i = 0; i < currentSize; i++) {
            Book book = bookList.getBook(i);
            if(book.getName().equals(name)) {
                System.out.println("存在这本书,信息如下:");
                System.out.println(book);
                return;
            }
        }
        System.out.println("不存在书名为‘"+name+"’的这本书!");
    }
}

ShowOperation

package operation;

import book.Book;
import book.BookList;

public class ShowOperation implements IOperation{
    @Override
    public void work(BookList bookList) {
        System.out.println("显示图书!");
        int currentSize = bookList.getUsedSize();
        for (int i = 0; i < currentSize; i++) {
            Book book = bookList.getBook(i);
            System.out.println(book);
        }
    }
}

ReturnOperation

package operation;

import book.Book;
import book.BookList;

import java.util.Scanner;

public class ReturnOperation implements IOperation{
    @Override
    public void work(BookList bookList) {
        System.out.println("归还图书!");
        Scanner sc = new Scanner(System.in);
        System.out.println("请写出你要归还图书的书名:");
        String name = sc.nextLine();

        int currentSize = bookList.getUsedSize();

        for (int i = 0; i < currentSize; i++) {
            Book book = bookList.getBook(i);
            if (book.getName().equals(name)) {
                book.setBorrowed(false);
                System.out.println("归还成功!");
                return;
            }
        }
        System.out.println("没有书名为'" + name + "'的书籍");
    }
}

ExitOperation

package operation;

import book.BookList;

public class ExitOperation implements IOperation{
    @Override
    public void work(BookList bookList) {
        System.out.println("退出系统");
        System.exit(0);
    }
}

3.6、完善User类

在User类中定义一个成员数组iOperations用于存储各个操作类,但是因为User被两个身份的用户类继承,而不同用户又有不同的操作方法,因此此时对成员数组iOperations声明不进行初始化。对iOperations的初始化留给继承于User的两个用户类。

User

package user;

import book.BookList;
import operation.IOperation;

public abstract class User {
    protected String name;
    protected IOperation[] iOperations;   //初始化留给继承User的子类

    public User(String name) {
        this.name = name;
    }
    public abstract int menu();

    public void doOperation(int choice, BookList bookList) {
        this.iOperations[choice].work(bookList);   //根据菜单的操作编号顺序确定iOperations数组中放置操作的顺序,
                                                   //从而可以直接使用操作编号作为数组的下标来访问对应的work方法
    }
}

接着参照menu()菜单去NormalUser类和AdminUser类中对iOperation数组进行各自的初始化。 

NormalUser

AdminUser

3.7、Mian类 

所有需要的类都以及准备完毕,现在开始完成测试类Main。

  1. 其中login()方法会返回两个用户类中的一个给到user接收,此时发生了向上转型
  2. 而根据login()方法得到的不同用户调用user.menu()会产生不同的菜单结果,此时说明发生了多态
  3. 给user.doOperation()传入操作编号choice和书架对象bookList,达到调用与编号对应的操作。
import book.BookList;
import operation.IOperation;
import user.AdminUser;
import user.NormalUser;
import user.User;

import java.util.Scanner;

public class Main {

    public static User login() {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入你的名字:");
        String name = sc.nextLine();
        System.out.println("请输入你的身份, 1:管理员  2:普通用户 ==》");
        int choice = sc.nextInt();
        if(choice == 1) {
            return new AdminUser(name);  //抽象类
        } else {
            return new NormalUser(name);
        }
    }
    public static void main(String[] args) {
        BookList bookList = new BookList();
        //此时user指向的是【管理员】还是【普通用户】是不知道的
        User user = login(); //向上转型
        while (true) {
            int choice = user.menu();   //多态
            //根据选择执行对应的操作
            user.doOperation(choice,bookList);
        }

    }
}

4、完整代码

由于篇幅有限,本篇博客的完整代码已上传到gitee,需要的小伙伴可以前往链接直接领取:

BookSystem/src · Nadez/study_Java - 码云 - 开源中国 (gitee.com)icon-default.png?t=N7T8https://gitee.com/nadezz/study_Java/tree/master/BookSystem/src

 

博主推荐:

【JavaSE】基础笔记 - 类和对象(上)-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/134232584?spm=1001.2014.3001.5502 

【JavaSE】基础笔记 - 类和对象(下)-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/134248822?spm=1001.2014.3001.5502 

【LeetCode力扣】42. 接雨水-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/134104222?spm=1001.2014.3001.5502 

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1220941.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习 天气识别

>- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营](https://mp.weixin.qq.com/s/Nb93582M_5usednAKp_Jtw) 中的学习记录博客** >- **&#x1f356; 原作者&#xff1a;[K同学啊 | 接辅导、项目定制](https://mtyjkh.blog.csdn.net/)** >- **&#x1f680;…

.nc格式文件的显示及特殊裁剪方式

最近我们遇到一个nc格式的文件&#xff0c;需要将它做成报告插图&#xff0c;bing搜索一番以后&#xff0c;了解到nc的全名为NetCDF(network Common Data Form)&#xff0c;是一种网络通用数据格式&#xff0c;广泛用于大气科学、水文、海洋学、环境模拟、地球物理等诸多领域。…

ArcGIS创建格网

目录 1、创建网格 2、裁剪边界外的网格 3、只保留边界内完整的网格 1、创建网格 首先&#xff0c;我们在创建渔网前&#xff0c;需要指定渔网覆盖的范围。这里我们就以四子王为例 在ArcMap软件中&#xff0c;我们依次选择“Toolboxes”→“Data Management Tools&#xff0…

基于STC12C5A60S2系列1T 8051单片机的模数芯片ADC0832实现模数转换应用

基于STC12C5A60S2系列1T 8051单片的模数芯片ADC0832实现模数转换应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍模数芯片ADC0832介绍通过模数芯片ADC0832把电压模…

【Linux】重定向|重新理解Linux下一切皆文件

文章目录 一、什么是重定向输出重定向的原理认识一下输出重定向的系统调用输出重定向的另外写法 二、浅谈输入重定向三、重定向和进程替换有冲突吗四、Linux下一切皆文件总结 一、什么是重定向 理解重定向之前&#xff1a;先理解一个叫做文件描述符的具体操作。 文件描述符&a…

C语言求0—7所能组成的奇数个数

完整代码&#xff1a; // 求0—7所能组成的奇数个数 //根据题意&#xff0c;应该是没有重复数字的&#xff0c;所以最大只能为八位数 //如果可以重复的话&#xff0c;那么位数就限制不了&#xff0c;然后奇数的个数就是无穷大了 #include <stdio.h>int main() {int coun…

万宾科技智能井盖传感器,提升市政井盖健康

市政井盖就是城市里不可或缺的基础设施之一&#xff0c;关于它的监测工作可马虎不得。它承载着保护市民的交通安全以及城市正常运转的重要使命。虽然现在城市化的速度很快&#xff0c;但是传统的市政井盖管理方式变得有些力不从心了。井盖的覆盖范围很广&#xff0c;如果单单依…

开启数据库审计 db,extended级别或os级别)并将审计文件存放到/opt/oracle/audit/下

文章目录 1、登录到数据库2、查看审计状态3、创建审计目录4、启用审计5、设置审计文件路径5、再次查看结果 1、登录到数据库 使用SQL*Plus或者其他Oracle数据库客户端登录到数据库。 sqlplus / as sysdba;2、查看审计状态 show parameter audit;目前是DB状态&#xff0c;并且…

【超好用的工具库】hutool-all工具库的基本使用

简介&#xff08;可不看&#xff09;&#xff1a; hutool-all是一个Java工具库&#xff0c;提供了许多实用的工具类和方法&#xff0c;用于简化Java开发过程中的常见任务。它包含了各种模块&#xff0c;涵盖了字符串操作、日期时间处理、加密解密、文件操作、网络通信、图片处…

计算机毕业设计 基于SpringBoot的医院档案管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

自动驾驶-BEV感知综述

BEV感知综述 随着自动驾驶传感器配置多模态化、多源化&#xff0c;将多源信息在unified View下表达变得更加关键。BEV视角下构建的local map对于多源信息融合及理解更加直观简洁&#xff0c;同时对于后续规划控制模块任务的开展也更为方便。BEV感知的核心问题是&#xff1a; …

【proverif】proverif的语法3-认证协议的验证代码-案例分析

proverif-系列文章目录 【proverif】proverif的下载安装和初使用【proverif】proverif的语法1-解决中间人攻击-代码详解【proverif】proverif的语法2-各种密码原语的编码【proverif】proverif的语法3-认证协议的验证代码-案例分析 (本文) 文章目录 proverif-系列文章目录前言一…

51单片机应用从零开始(六)·逻辑运算

51单片机应用从零开始&#xff08;一&#xff09;-CSDN博客 51单片机应用从零开始&#xff08;二&#xff09;-CSDN博客 51单片机应用从零开始&#xff08;三&#xff09;-CSDN博客 51单片机应用从零开始&#xff08;四&#xff09;-CSDN博客 51单片机应用从零开始&#xff08;…

【入门篇】1.1 redis 基础数据类型详解和示例

文章目录 1. 简介2. Redis基础数据类型2.1 String类型场景示例常用命令示例 2.2 List类型场景示例 2.3 Set类型场景示例 2.4 Hash类型场景示例 2.5 Sorted Set类型 3. 使用Redis存储数据的注意事项1. 内存管理2. 数据持久化3. 高并发下的性能考量 4. 参考资料 1. 简介 Redis概…

springMvc中的拦截器【巩固】

先实现下想要的拦截器功能 package com.hmdp.utils;import com.hmdp.entity.User; import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Ht…

【SpringMvc】SpringMvc +MyBatis整理

&#x1f384;欢迎来到边境矢梦的csdn博文&#x1f384; &#x1f384;本文主要梳理 Java 框架 中 SpringMVC的知识点和值得注意的地方 &#x1f384; &#x1f308;我是边境矢梦&#xff0c;一个正在为秋招和算法竞赛做准备的学生&#x1f308; &#x1f386;喜欢的朋友可以关…

python_主动调用其他类的成员

# 主动调用其他类的成员 # 方式一: class Base(object):def f1(self):print("5个功能") class Foo(object):def f1(self):print("3个功能")# Base.实例方法(自己传self),与继承无关Base.f1(self)obj Foo() obj.f1()print("#"*20)# 方式二:按照类…

Rockdb简介

背景 最近在使用flink的过程中&#xff0c;由于要存储的状态很大&#xff0c;所以使用到了rockdb作为flink的后端存储&#xff0c;本文就来简单看下rockdb的架构设计 Rockdb设计 Rockdb采用了LSM的结构&#xff0c;它和hbase很像&#xff0c;不过严格的说&#xff0c;基于LS…

希亦ACE和小吉内衣洗衣机选哪个?两款洗衣机对比

内衣洗衣机可以称得上是实现幸福的小家电&#xff0c;它不仅懒人的福音还是我们打工人的福音&#xff0c;在每天下班之后可以有时间休息了&#xff0c;洗完澡还有要手洗内衣裤&#xff0c;真的很痛苦&#xff0c;拥有了内衣洗衣机简直是一件非常幸福的事情&#xff0c;但现在市…

wpf devexpress Property Grid创建属性定义

WPF Property Grid控件使用属性定义定义如何做和显示 本教程示范如何绑定WP Property Grid控件到数据和创建属性定义。 执行如下步骤 第一步-创建属性定义 添加PropertyGridControl组件到项目。 打开工具箱在vs&#xff0c;定位到DX.23.1: Data 面板&#xff0c;选择Prope…