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

 

目录

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 

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

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

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

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

反转字符串中的单词

给你一个字符串 s &#xff0c;请你反转字符串中 单词 的顺序。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。 返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。 注意&#xff1a;输入字符串 s中可能会存在前导空格、尾随空格…

【MATLAB源码-第81期】基于matlab的polar码三种译码算法比较(SC,SCL,BP)。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 Polar码&#xff08;Polar Codes&#xff09;是一种前向纠错编码方法&#xff0c;被认为是实现信道容量极限的编码方法之一。它在某些场合下&#xff0c;如5G通信标准中得到了应用。Polar码的主要译码算法包括Successive Can…

短期经济波动:均衡国民收入决定理论(三)

短期经济波动&#xff1a;国民收入决定理论(三) 文章目录 短期经济波动&#xff1a;国民收入决定理论(三)[toc]1 总需求曲线及其变动1.1 总需求曲线含义1.2 总需求曲线推导1.2.1 代数推导1.2.2 几何推导 1.3 AD曲线及其变动1.3.1 扩张性财政政策1.3.2 扩张性货币政策 2 总供给曲…

面试其他注意事项

面试其他注意事项 一、面试反问 这个岗位的日常工作和主要职责是什么&#xff1f;咱们这边主要负责什么业务&#xff0c;用到了哪些技术呢&#xff1f;对于我们校招生有没有培养体系呢&#xff1f;脱产培训&#xff0c;还是边工作边熟悉&#xff1f;会有导师带嘛&#xff1f;…

【Spring】IoC容器的一些总结与补充

文章目录 1. 创建容器的两种方式相对路径导入绝对路径导入 2. 获取Bean的三种方式getBean后强转类型getBean内写明类别根据类别获取bean 3. 容器层次结构4. BeanFactory5. bean的总结6. 注入的总结 1. 创建容器的两种方式 相对路径导入 ApplicationContext ctx new ClassPat…

一篇文章让你彻底掌握 shell 语言

一篇文章让你彻底掌握 shell 语言 1. 前序2. shell介绍2.1. 什么是shell2.2. 什么是shell编程2.3. shell解释器3. 基本语法3.1 第一个shell脚本3.2 注释3.3. echo3.3.1 **输出字符串**3.3.2 **输出变量**3.3.3 **启用转义字符**3.3.4 **向文件添加内容**3.3.5 **输出命令执行结…

NET8 ORM 使用AOT SqlSugar

.NET AOT8 基本上能够免强使用了, SqlSugar ORM也支持了CRUD 能在AOT下运行了 Nuget安装 SqlSugarCore 具体代码 StaticConfig.EnableAot true;//启用AOT 程序启动执行一次就好了//用SqlSugarClient每次都new,不要用单例模式 var db new SqlSugarClient(new ConnectionC…

Mac M1 M1 pro安装 protobuf 2.5.0

因为项目中的protobuf是2.5.0版本&#xff0c;但是旧版本的protobuf 不支持M1&#xff0c;此时需要修改源码重新编译 操作步骤&#xff1a; 从git上面下载对应版本的protobuf&#xff0c;地址&#xff1a;Release Protocol Buffers v2.5.0 protocolbuffers/protobuf GitHub…

linux进程间通信之共享内存(mmap,shm_open)

共享内存&#xff0c;顾名思义就是允许两个不相关的进程访问同一个逻辑内存&#xff0c;共享内存是两个正在运行的进 程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常为同一段物理内存。进程可以将同一段物理内存连接到他们自己的地址空间中&#xff0c…

超详细的Jmeter接口测试教程以及接口测试流程

一、Jmeter简介 Jmeter是由Apache公司开发的一个纯Java的开源项目&#xff0c;即可以用于做接口测试也可以用于做性能测试。 Jmeter具备高移植性&#xff0c;可以实现跨平台运行。 Jmeter可以实现分布式负载。 Jmeter采用多线程&#xff0c;允许通过多个线程并发取样或通过…

Redis实战篇(1)

实战篇Redis 短信登录 这一块我们会使用redis共享session来实现 商户查询缓存 通过本章节&#xff0c;我们会理解缓存击穿&#xff0c;缓存穿透&#xff0c;缓存雪崩等问题&#xff0c;让小伙伴的对于这些概念的理解不仅仅是停留在概念上&#xff0c;更是能在代码中看到对应…

APP安全加固怎么做?加固技术、加固方法、加固方案

前面的文章中我们为大家介绍了移动应用安全检测的测试依据、测试方法、和测试内容&#xff0c;本文我们着重分享App安全加固的相关内容。 &#xff08;安全检测内容&#xff09; 通过前面的文章我们知道了app安全检测要去检测哪些内容&#xff0c;发现问题后我们如何去修复&am…

SpringCloud FeignClient声明式服务调用采坑记录(A调用服务B/C,B/C重启后必须重启A后才能成功调用配置项)

SpringCloud FeignClient声明式服务调用&#xff08;A调用服务B/C&#xff0c;B/C重启后必须重启A后才能成功调用配置项采坑记录&#xff09; 1. 报错&#xff08;info级别的警告信息&#xff09;2. 原因&#xff1a;使用了默认了cache负载均衡&#xff0c;或者禁用了ribbonLoa…

C语言之深入指针(三)(详细教程)

C语言之深入指针 在学习这篇博客之前建议先看看这篇博客C语言之深入指针&#xff08;二&#xff09; 里面详细介绍了指针的 传值调用和传址调用数组名的理解使用指针访问数组⼀维数组传参的本质 文章目录 C语言之深入指针1 二级指针1.1 二级指针的介绍1.2 二级指针的使用 2 指…

【LeetCode:2760. 最长奇偶子数组 | 模拟 双指针】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

【教3妹学编程-算法题】高访问员工

2哥 : 3妹&#xff0c;今天周五怎么还下班这么晚啊&#xff1f;这么晚了才回来 3妹&#xff1a;项目快上线了&#xff0c; 最近事情比较多&#xff0c;再累也要干&#xff0c; 撸起袖子加油干&#xff01; 2哥 : 辛苦辛苦&#xff0c; 哎&#xff0c;你看到王自如格力那个采访了…

京东推出数据平台云海 API接口将达700个

1月16日消息&#xff0c;继上周面对企业用户发布京东电商云解决方案后&#xff0c;日前&#xff0c;京东云平台又发布了全新的数据开放平台——“云海”&#xff0c;以开放商家、商品、点击流等相关数据。 在京东主办&#xff0c;思路网协办的京东开放云服务合作伙伴2014峰会&…

mysql中的各种日志文件redo log、undo log和binlog

mysql中的各种日志文件redo log、undo log和binlog mysql中的各种日志文件redo log、undo log和binlog1.MySQL日志文件类型2.redo log日志2.1 作用2.2工作原理&#xff1a;2.3详解 3.undo log日志4.binlog日志5.总结 mysql中的各种日志文件redo log、undo log和binlog 1.MySQL…

【Mysql】Mysql内置函数介绍

&#x1f308;欢迎来到Python专栏 &#x1f64b;&#x1f3fe;‍♀️作者介绍&#xff1a;前PLA队员 目前是一名普通本科大三的软件工程专业学生 &#x1f30f;IP坐标&#xff1a;湖北武汉 &#x1f349; 目前技术栈&#xff1a;C/C、Linux系统编程、计算机网络、数据结构、Mys…

解密.locked1勒索病毒:专家级策略保护您的数据免受勒索攻击

导言&#xff1a; 在当今数字化的世界中&#xff0c;勒索病毒的威胁日益严峻。.locked1 勒索病毒作为其中的一种&#xff0c;采用高级的加密算法对用户文件进行加密&#xff0c;要求支付赎金以获取解密密钥。本文91数据恢复将介绍如何面对.locked1 勒索病毒&#xff0c;有效恢…