本文目录导读:

这是一个非常棒的Java学习收尾方式,与其零散地看知识点,不如通过一个综合性、贴近实际开发的案例来串联起Java的核心技术。
为了覆盖从基础语法到高级特性,再到工程实践,我为你设计了一个经典的“小型图书管理系统(控制台版)”案例,它包含了CRUD、集合、I/O、异常、多态、枚举等核心内容。
案例名称:简易图书管理系统
核心需求
- 角色:普通用户(User)、管理员(Admin)。
- 功能:
- 登录/注册(区分角色)。
- 图书管理(管理员):添加、删除、查看所有图书、修改图书信息。
- 借书/还书(用户):借阅、归还、查看已借图书。
- 数据持久化:程序退出后,数据不丢失(使用文本文件或二进制文件存储)。
知识覆盖点
- 面向对象:类、对象、封装、继承(
Book、User、AdminUser)、多态(用户接口)。 - 集合框架:使用
ArrayList或HashMap存储图书和用户。 - 异常处理:自定义异常(如
BookNotFoundException、StockNotEnoughException)。 - I/O 流:使用
ObjectOutputStream/ObjectInputStream保存和加载对象。 - 枚举:图书分类(文学、科技、历史等)。
- 泛型:存储图书的
ArrayList<Book>。 - 常用API:
Scanner、String、Date。
代码结构设计与实现
基础类与核心抽象
我们定义核心的实体和接口,这是面向对象的基础。
import java.io.Serializable;
import java.util.Date;
// Book 类必须实现 Serializable 接口,以便进行对象序列化
class Book implements Serializable {
private static final long serialVersionUID = 1L;
private String isbn; // 唯一标识
private String title;
private String author;
private Category category; // 枚举类型
private int stock; // 库存数量
private int borrowCount; // 已借出数量
// 构造器、getters、setters、toString... (此处省略,实际开发中请用IDE生成)
}
// 图书分类枚举
enum Category {
LITERATURE("文学"), SCIENCE("科技"), HISTORY("历史"), OTHER("其他");
private String description;
private Category(String description) { this.description = description; }
public String getDescription() { return description; }
}
// 用户抽象类
abstract class User implements Serializable {
private static final long serialVersionUID = 1L;
private String username;
private String password;
// 构造器、getters、setters...
}
数据持久化(I/O模块)
使用 Java 的 ObjectInputStream 和 ObjectOutputStream 实现。
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class DataPersistence {
private static final String BOOK_FILE = "books.dat";
private static final String USER_FILE = "users.dat";
// 保存图书列表到文件
public static void saveBooks(List<Book> books) {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(BOOK_FILE))) {
oos.writeObject(books);
} catch (IOException e) {
System.err.println("保存图书数据失败: " + e.getMessage());
}
}
// 加载图书列表
@SuppressWarnings("unchecked")
public static List<Book> loadBooks() {
File file = new File(BOOK_FILE);
if (!file.exists()) return new ArrayList<>();
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
return (List<Book>) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
System.err.println("加载图书数据失败,请检查文件完整性: " + e.getMessage());
return new ArrayList<>(); // 返回空列表,避免程序崩溃
}
}
// 保存用户列表(逻辑与上类似,略)
public static void saveUsers(List<User> users) { /* ... */ }
public static List<User> loadUsers() { /* ... */ return new ArrayList<User>(); }
}
业务逻辑层(Service)
处理图书和用户的业务逻辑。
// 自定义异常
class BookNotAvailableException extends Exception {
public BookNotAvailableException(String message) { super(message); }
}
class LibraryService {
private List<Book> books;
private List<User> users;
public LibraryService() {
// 启动时加载数据
this.books = DataPersistence.loadBooks();
this.users = DataPersistence.loadUsers();
}
// 添加图书(管理员)
public boolean addBook(Book book) {
// 检查 ISBN 是否重复
for (Book b : books) {
if (b.getIsbn().equals(book.getIsbn())) {
return false; // 已存在
}
}
books.add(book);
return true;
}
// 借书(用户)
public boolean borrowBook(String isbn, User user) throws BookNotAvailableException {
for (Book book : books) {
if (book.getIsbn().equals(isbn)) {
if (book.getStock() > 0) {
book.setStock(book.getStock() - 1);
// 可以在这里记录借书历史,或关联到用户
return true;
} else {
throw new BookNotAvailableException("图书库存不足,无法借阅");
}
}
}
throw new BookNotAvailableException("未找到该ISBN的图书");
}
// 程序关闭时回调,保存数据
public void shutdown() {
DataPersistence.saveBooks(this.books);
DataPersistence.saveUsers(this.users);
}
}
用户界面层(UI / 控制台)
模拟登录和功能菜单。
public class LibraryApp {
private static LibraryService libraryService = new LibraryService();
public static void main(String[] args) {
System.out.println("欢迎使用图书管理系统");
User currentUser = login();
if (currentUser != null) {
if (currentUser instanceof AdminUser) {
adminMenu((AdminUser) currentUser);
} else {
userMenu((NormalUser) currentUser);
}
}
// 程序退出前,将内存数据写回磁盘
libraryService.shutdown();
System.out.println("数据已保存,感谢使用!");
}
private static void adminMenu(AdminUser admin) {
while (true) {
System.out.println("1. 查看所有图书");
System.out.println("2. 添加图书");
System.out.println("3. 删除图书");
System.out.println("0. 退出系统");
int choice = new Scanner(System.in).nextInt();
switch (choice) {
case 1: displayAllBooks(); break;
case 2: addBook(); break;
// case 3: deleteBook(); break;
case 0: return; // 退出菜单,由主方法处理 shutdown
default: System.out.println("输入无效");
}
}
}
// 具体实现方法(displayAllBooks, addBook等)此处略...
}
总结与反思:为什么这是一个“好”案例?
这个案例完美地串联了Java核心技术点,让我们通过一个表格来总结:
| Java知识点 | 在本案例中的应用 |
|---|---|
| 面向对象 | Book、User、AdminUser、NormalUser 的继承与多态。 |
| 集合框架 | ArrayList 管理图书列表,HashMap 可管理用户密码。 |
| I/O 流 | ObjectStream 实现对象序列化,实现程序数据的“记忆”功能。 |
| 异常处理 | try-with-resources 自动关闭流;自定义异常处理业务错误。 |
| 枚举 | Category 类型安全地表示图书分类。 |
| 接口 | 可为 User 定义 MenuAction 接口,体现“接口驱动设计”思想。 |
| 泛型 | ArrayList<Book> 确保类型安全。 |
扩展性思考(面试加分项)
这个案例虽然基础,但可以轻松扩展到更复杂的场景,你可以借此展示你的设计能力:
- 数据库化:将文件存储改为
JDBC + MySQL。 - 图形化:将控制台界面改为
Swing或JavaFX。 - 线程安全:引入
Collections.synchronizedList()或ReentrantLock处理高并发。 - 设计模式:使用 单例模式 管理
LibraryService,使用 工厂模式 创建不同的User对象。
通过动手编码并理解这个案例,你不仅复习了Java语法,更重要的是锻炼了编程思维和架构能力,这对于应对面试或实际项目开发都很有帮助。