学了java想要练手,图书管理系统这个项目非常适合你
项目需求大体想法:
能够查看书籍,借阅书籍,打印书籍等功能。输出姓名后能进入为普通用户模式或者管理员模式。
各类包之间协同合作之间关系讲解。
做这个项目的始终是为了对于刚学java的同学,在学完面向对象,和一部分类和枚举,异常学完之后就可以尝试了。
这个项目没有多高大,这不过是对java基础知识的巩固,没有Swing图形界面,和前端知识,也没有引入数据库的知识jdbc。但是毕竟是项目,难度还是有的,对于初学者来说既能巩固知识,又能拓展思维,学会这个项目,期末考试考个90+不成问题,而且对后期真正项目起到很好的帮助。
一 .整体思路
书籍类为书籍的封装信息,和返回信息。有书,也要有书架,书架就是存放书籍的具体信息。至于为什么会有书架和书籍类之分,那就与代码可维护性,功能分析有很好作用。对于接口,就是具体代码实现了,像打印书籍,归还书籍,停止退出系统,查找书籍,增加书籍,删除书籍。在上面我说过有普通用户和管理员之分,那么就有这两类,这两类是实现菜单打印,和连接接口的功能。
(1)书籍包
键一个book包
Book是书籍类
这是基本书籍封装信息:
package book;
public class Book {
private String name; //书名
private String author; //作者
private String dynasty; //朝代
private int price; // 价格
private boolean isBorrowed; //是否借出
private String 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 String getDynasty() {
return dynasty;
}
public void setDynasty(String dynasty) {
this.dynasty = dynasty;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public boolean isBorrowed() {
return isBorrowed;
}
public void setBorrowed(boolean borrowed) {
isBorrowed = borrowed;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
上面的方法你准备怎么写呢?不会一步一步敲出来把?!
①点击鼠标右键,弹出generate,点击
②弹出getter and setter,点击
进入之后全选后确定就会出现我们想要的方法了
上面是对Book类的部分代码,当我们有需要时再去修改,跟着我的思路来才是一个程序员思维提升的好方法。
BookList是书架类
书架类我们首先做的就是建立动态数组,为了存储书籍,这里用到了数组的知识。
package book;
public class BookList {
//建立一个动态数组存放信息
//书架存放Book里面的书籍信息,那么该书籍是Book数组
// private Book[]books=new Book[10];这样做可维护性不高所以把10改成
private static final int number=20;
private Book[]books=new Book[number];
private int usedSize;
public BookList(){
books[0]=new Book("三国演义","罗贯中","明代","小说",520);
books[1]=new Book("红楼梦","曹雪芹","清朝","小说",521);
books[2]=new Book("西游记","不知道","明代","小说",250);
this.usedSize=3;
}
在这段代码中开辟了存放20的数组,下面的代码则是对书架中书籍的具体化,但是,在Book类中我们没有构建有参的构造方法,所以要加上。
public Book(String name, String author, String dynasty, String type, int price) {
this.name = name;
this.author = author;
this.dynasty = dynasty;
this.type = type;
this.price = price;
}
(2)用户包
新建一个userall1包
建一个User抽象类
package userall1;
import book.*;
import opera.IPinterfrance;
//抽象类---》用户
public abstract class User {
//写一个姓名
protected String name; //子类无法继承
public User(String name){
this.name=name;
}
//写了一个抽象方法菜单
public abstract int menu();
}
建一个AdminUser管理员子类
package userall1;
import opera.*;
import java.util.*;
//AdmiinUser是User的子类
public class AdminUser extends User{
public AdminUser(String name) {
super(name);
}
建一个NormalUser普通用户子类
package userall1;
import opera.*;
import java.util.Scanner;
public class NormalUser extends User{
public NormalUser (String name){
super(name);
}
建立用户包的目的是为了区分管理员还是普通用户,并在本类中实现特定的功能。到这里代码还没有完全实现,思路要一步一步来,这里这不过是输入名字后,保存名字信息。
(三)主函数
程序的开始是主函数,代码就是在主函数开始调试的,当你不明白带代码是你就要从主函数一步一步开始分析。
先对主函数进行分析大体了解流程,接口中的具体实现方法最后看。因为他对全局影响不大。
在主函数中写一个登录方法
public class Main {
//写一个登录类,返回值是User,请输入你的名字,选择身份
//static为什么要用static与后面有关
public static User login() {
System.out.println("请输入你的姓名:");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();//输入字符串scanner.nextLine()
System.out.println("请输入你的身份:1-》管理员 2-》普通用户");
int choice = scanner.nextInt();
if (choice == 1) {
return new AdminUser(name); //下面子类通过父类继承
}
if (choice == 2) {
return new NormalUser(name);
} else {
System.out.println("输入错误!");
return login();
}
}
主方法里面要调用登录方法。
public static void main(String[] args){
User user = login(); //login()返回后是new AdminUser(name)父类通过子类实例化
BookList bookList=new BookList();
while(true)
{
int choice=user.menu();
user.dowork(choice,bookList);
}
}
在主方法中我们看到user.menu(),所以user中要有抽象方法menu。dowork,而dowork方法是从user里调用的,目的是为了什么呢?我们加上代码
menu
user:
管理员具体菜单代码:
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.退出系统");
}
普通用户菜单代码:
public int menu(){
System.out.println("_________________");
System.out.println("hello,"+name+"~");
System.out.println("1.查找图书!");
System.out.println("2.借阅图书!");
System.out.println("3.归还图书!");
System.out.println("0.退出系统!");
}
光有菜单还不行,还要输入数字,输入数字后转接到具体实现类,那么就要再一次引入数组,通过数组下标来实现接口连接
在user引入:
在管理员类普通用户类中还要引入:
this.ioPerations = new IOPeration[]{//引用,这边用super也可以,因为这里没有同名的,不需要做区分。用this最好
new ExitOperation(),
new FindOperation(),
new BrrowOperation(),
new ReturnOperation(), //为什么会放在子类因为子类接口不相同
//以动态方式申请内存。拿到变量后,我们就给他们分配内存
};
具体实现代码:
user:
普通用户和管理员都要在菜单下面加入输入数字语句:
Scanner scanner=new Scanner(System.in);
int choice=scanner.nextInt();
return choice;
(四)接口实现包
建一个接口Ipinterfrance,为了实现各个功能的。
package opera;
import book.BookList;
import java.sql.SQLException;
//接口实现普通用户和管理员的功能
public interface IOPeration {
//抽象方法功能是针对图书的
void work(BookList bookList) throws ClassNotFoundException, SQLException;
}
二 .具体接口代码
(1)展示图书
package opera;
import book.*;
public class Showopera implements IPinterfrance{
public void work(BookList bookList){ //传入图书变量
System.out.println("展示图书!");
int current=bookList.getUsedSize();
for(int i=0;i<current;++i)
{
System.out.println(bookList.getBooks(i));
}
}
}
(2)增加图书
package opera;
import book.*;
import java.sql.*;
import java.util.*;
public class AddOperation implements IOPeration{
//重写方法
@Override
public void work(BookList bookList) throws ClassNotFoundException, SQLException {
System.out.println("新增图书!");
Scanner scanner=new Scanner(System.in);
System.out.println("请输入新增图书名字:");
String name=scanner.nextLine();
System.out.println("请输入新增图书作者:");
String auther=scanner.nextLine();
System.out.println("请输入新增图书价格:");
int price=scanner.nextInt();
Scanner scanner2=new Scanner(System.in);
System.out.println("请输入新增图书类型:");
String type=scanner2.nextLine();
System.out.println("请输入新增图书作者朝代:");
String dynasty=scanner2.nextLine();
Book book=new Book(name,auther,dynasty,price,type);
int currentSize= bookList.getUsedSize();
for(int i=0;i<currentSize;++i){
Book temp=bookList.getBooks(i); //为什么会不同?? temp不行
if(temp.getName().equals(name)){//判断查找图书名字是否相同
System.out.println("已经有这本书了");
return;
}
}
bookList.setBooks(book);
System.out.println("新增图书成功");
//新图书+1
bookList.setUsedSize(currentSize+1);
}
}
这里的setBooks是书架类里面新增图书的方法:
(3)停止系统
停止系统非常简单,就是:
package opera;
import book.BookList;
public class ExitOperation implements IOPeration{
@Override
public void work(BookList bookList) {
System.out.println("退出系统!");
System.exit(0); //退出系统
}
}
(4)借阅系统
package opera;
import book.BookList;
import java.util.*;
import book.*;
public class BrrowOperation implements IOPeration{
@Override
public void work(BookList bookList) {
System.out.println("借阅图书");
System.out.println("请输入要借阅的图书");
Scanner scanner=new Scanner(System.in);
String name=scanner.nextLine();
int curentSize= bookList.getUsedSize();
int x=1;
for(int i=0;i<curentSize;i++){
Book temp=bookList.getBooks(i);
if((temp.getName().equals(name))&&!temp.isBorrowed()){ //
{
temp.setBorrowed(true);
x=0;
System.out.println("借阅成功!");
return;
}
}
}
if(x==1){
//写了个判断条件让我想到了冒泡排序
System.out.println("没有该图书");
}
}
}
(5)归还图书
package opera;
import book.BookList;
import java.util.*;
import book.*;
public class ReturnOperation implements IOPeration{
@Override
public void work(BookList bookList) {
System.out.println("归还图书!");
System.out.println("请输入要归还的图书名字:");
Scanner scanner=new Scanner(System.in);
String name=scanner.nextLine();
int curentSize= bookList.getUsedSize();
for(int i=0;i<curentSize;i++){
Book temp=bookList.getBooks(i);
if((temp.getName().equals(name))&&temp.isBorrowed()){
{
temp.setBorrowed(false);//变成归还状态false
System.out.println("归还成功!");
return;
}
}
}
}
}
(6)查找书籍
package opera;
import book.*;
import java.util.Scanner;
public class FindOperation implements IOPeration{
@Override
public void work(BookList bookList) {
System.out.println("查找图书!");
System.out.println("请输入要输入的图书");
Scanner scanner=new Scanner(System.in);
String name=scanner.nextLine();
int currentSize= bookList.getUsedSize();
for(int i=0;i<currentSize;++i)
{
Book book=bookList.getBooks(i);
if(book.getName().equals(name)) //判断书籍是否相同
{
System.out.println("找到了");
System.out.println(book);
return;
}
}
System.out.println("没有这本书");
}
}
(7)删除书籍
package opera;
import book.*;
import java.util.*;
public class DelOperation implements IOPeration{
@Override
public void work(BookList bookList) {
System.out.println("删除图书!");
System.out.println("请输入要删除的图书名字");
Scanner scanner=new Scanner(System.in);
String name=scanner.nextLine();
int currentSize= bookList.getUsedSize();
int index=-1;
//删除的思路很简单就是减小下标很粗暴
for(int i=0;i<currentSize;i++){
Book temp=bookList.getBooks(i);
if(temp.getName().equals(name))
{
index=i;
break;
}
for(int j=index;j<currentSize;j++)
{
Book book=bookList.getBooks(j+1);
bookList.setBooks(j,book); //把上面的数放到该位置为以后-1做铺垫
}
}
bookList.setUsedSize(currentSize-1);//修改size值
bookList.setBooks(currentSize-1,null);//因为删除的是对象,所以把地址置为null,就没有人引用了
}
}
三 .疑难分析(看了5k点赞的看不懂的这里都有详细讲解)
如果对这个项目很熟悉的话,直接看我的源码和疑难分析。
这段代码就是显示代码执行的,通过书架类中getbooks方法调用
如果对这个项目有所疑问请私信我,大家一定要捋一下代码,不会的地方私信我或者在评论区留言我一定会给大家回复!!!
四 .源码展示
主方法代码:
book包
Book类
package book;
public class Book {
//书的名字,类型,作者,价格,是否借出
private String name;
private String author;
private double price;
private boolean isBorrowed;//是否借出
private String type;
//此处点击鼠标,generate +Getter+Setter+全选
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 double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public boolean isBorrowed() {
return isBorrowed;
}
public void setBorrowed(boolean borrowed) {
isBorrowed = borrowed;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
//写一个构造方法不是特别明白
public Book(String name,String author,double price,String type){
this.author=author;
this.name=name;
this.type=type;
this.price=price;
}
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
", type='" + type + '\'' +
", isBorrowed=" +(isBorrowed==true?" 已借出":" 未借出") +
'}';
}
}
BookList类
package book;
import java.sql.*;
//写一个书架
public class BookList {
//写数组 数据类型[]变量名=new 数据类型[大小]
//private Book[]books=new Book[10];
//上面的写法会可写性不高
private static final int DEFAULT_SIZE=10;
private Book[]books=new Book[DEFAULT_SIZE];
private int usedSize;
//虽然可以在类中直接初始化变量,但不定义构造方法可能会导致初始化逻辑分散
// 和不清晰。构造方法提供了一种清晰、集中的方式来初始化对象的状态,
// 这对于保持代码的组织、可读性和可维护性至关重要。
public BookList(){
books[0]=new Book("三国演义","罗贯中",55,"小说");
books[1]=new Book("红楼梦","曹雪芹",50,"小说");
books[2]=new Book("三国志","陈寿",58,"史书");
this.usedSize=3;
}
public Book getBooks(int pos) {
return this.books[pos];
} //显示数据
//记录当前数组有几本书
//记录当前数组
public void setBooks(Book book){
this.books[usedSize]=book;
} //通过这个方法增加书籍到这里面
public void setBooks(int pos,Book book) {
this.books[pos] = book;
}
public int getUsedSize() {
return usedSize;
}
public void setUsedSize(int usedSize) {
this.usedSize = usedSize;
}
}
user包
管理员类
package users;
import java.util.Scanner;
import opera.*;
public class AdminUser extends User{
public AdminUser(String name){
super(name);
this.ioPerations=new IOPeration[]{//引用,这边用super也可以,因为这里没有同名的,不需要做区分。用this最好
new ExitOperation(),
new FindOperation(),
new AddOperation(),
new DelOperation(),
new ShowOperation() //难于理解
};
}
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("请输入序号:");
Scanner scanner=new Scanner(System.in);
int choice=scanner.nextInt();
return choice;
}
}
普通用户类
package users;
import java.util.Scanner;
import opera.*;//包里面全部调用
public class NormalUser extends User{
public NormalUser(String name) {
super(name);
//动态开辟数组
this.ioPerations = new IOPeration[]{//引用,这边用super也可以,因为这里没有同名的,不需要做区分。用this最好
new ExitOperation(),
new FindOperation(),
new BrrowOperation(),
new ReturnOperation(), //为什么会放在子类因为子类接口不相同
//以动态方式申请内存。拿到变量后,我们就给他们分配内存
};
}
public int menu(){
System.out.println("_________________");
System.out.println("hello,"+name+"~");
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;
}
}
User抽象类
package users;
import opera.*;
import book.*;
import java.sql.SQLException;
public abstract class User { //抽象类
protected String name; //不能为私有,否则管理员类或者普通类无法继承
protected IOPeration[] ioPerations;//定义了数组
//构造方法
public User(String name){
this.name=name;
}
public void doWork(int choice, BookList bookList) throws SQLException, ClassNotFoundException {//通过选择的操作,去选择执行数组下的哪个操作
this.ioPerations[choice].work(bookList);
}
public abstract int menu();
}
接口
package opera;
import book.BookList;
import java.sql.SQLException;
//接口实现普通用户和管理员的功能
public interface IOPeration {
//抽象方法功能是针对图书的
void work(BookList bookList) throws ClassNotFoundException, SQLException;
}