Book 应设计为抽象类,定义共性字段(isbn、title、author)和抽象方法(getDisplayInfo、canBorrow),以便 EBook 等子类专注自身逻辑实现多态扩展。

Book 类怎么设计才支持多态扩展
继承多态不是为了“用上”而用,而是为未来加新书类型(比如 EBook、Audiobook)留出不改主逻辑的余地。所以 Book 必须是抽象类或接口,不能是具体类。
常见错误:把 Book 写成普通 class,后面加 EBook 时发现借阅规则、显示格式全得复制粘贴逻辑,违背多态本意。
-
Book定义为abstract class,抽离共性字段:isbn、title、author - 把行为差异点声明为抽象方法:
abstract String getDisplayInfo()、abstract boolean canBorrow() - 子类重写时只专注自身逻辑,比如
EBook的canBorrow()可能永远返回true,而ReferenceBook返回false
控制台交互里怎么避免 Scanner 输入错乱
Scanner 的 nextLine() 和 nextInt() 混用是高频崩溃点——nextInt() 不吞换行符,下个 nextLine() 直接读到空字符串,导致菜单跳过、ID 输入失效。
使用场景:用户选菜单编号(int),再输书名(String),结果书名总为空。
立即学习“Java免费学习笔记(深入)”;
- 统一用
nextLine()读所有输入,数字用Integer.parseInt()转 - 或者每次调用
nextInt()后紧跟一次scanner.nextLine()清缓冲区 - 别在循环里反复 new
Scanner(System.in),一个实例复用到底
图书集合用 ArrayList 还是 HashMap 存
控制台系统不需要高并发或海量数据,但得支撑快速按 ISBN 查书、遍历列表展示、删除指定对象——这些操作的性能和编码清晰度直接取决于容器选型。
容易踩的坑:用 ArrayList<Book> 存所有书,查 ISBN 时写 for 循环遍历,后期加到 200 本书时明显卡顿;或用 HashMap<String, Book> 却把 ISBN 当 key,删书时还得遍历 value 找对象,白瞎了哈希优势。
- 主存储用
ArrayList<Book>:增删顺序自然,遍历打印方便,内存开销小 - 额外建一个
Map<String, Book>(key =isbn)做索引:查 ISBN 时O(1),不破坏主列表结构 - 所有增删操作同步更新两个结构,封装进
LibraryManager类里,外部不感知
main 方法里为什么别写满业务逻辑
控制台程序容易写成“main 里一堆 System.out.println + if-else 套娃”,看似跑通,但加个“按作者搜索”功能就得翻 50 行代码改分支,且无法单元测试。
本质问题是职责混杂:输入解析、业务判断、状态维护、输出渲染全挤在一起。
-
main只做三件事:初始化LibraryManager、启动菜单循环、分发用户输入到对应方法 - 每个菜单项(如“添加图书”)对应一个独立方法,例如
handleAddBook(Scanner sc) - 所有图书数据操作委托给
LibraryManager,它内部管集合、索引、校验,不碰System.in/out
多态的价值不在语法正确,而在新增一种书时,你只改两处:加一个子类、在工厂方法里加一行 case "ebook": return new EBook(...)。其余菜单、存储、显示逻辑全不动——这才是设计在控制台小项目里真正省下的时间。









