封装是用边界、权限和契约管控数据与行为;需按职责分包、属性私有+行为暴露、接口统一入口、构造器调用set校验,确保修改可控、扩展无感、维护清晰。

直接说重点:封装不是加几个 private 和 get/set 就完事,而是用边界、权限和契约把数据和行为真正管起来。对第一个控制台项目(比如图书管理系统)来说,合理封装能让你改一处不崩全盘、加功能不翻车、别人接手不抓狂。
按职责分包,让每个类只干一件事
别把所有代码塞进一个 Main.java 或 Book.java 里。参考标准分层结构:
- book 包:只放 Book(单本图书的属性+校验逻辑)、BookList(书架数组+增删查基础操作),不碰菜单、不处理用户权限
- user 包:User 是抽象父类,定义 login()、showMenu() 这类共性;AdminUser 和 NormalUser 各自实现自己能干的操作,不越界
- ioperations 包:每个功能一个类(AddOperation、BorrowOperation),只专注“做这件事”,不掺杂输入输出或流程控制
这样改借阅逻辑,只动 BorrowOperation;换管理员菜单,只改 AdminUser.showMenu() —— 影响范围清晰可控。
属性私有 + 行为暴露,用方法代替字段直写
比如 Book 类里:
- 把 name、author、isBorrowed 全设为 private
- 提供 setIsBorrowed(boolean b),内部自动校验:不能对已借出的书重复借,也不能对未借出的书重复还
- 提供 toString() 统一格式化打印,而不是在 Main 里拼字符串
以后想加借阅时间戳、记录操作人,只改 Book 类内部,所有调用方完全无感。
接口统一入口,把“怎么做”藏起来
定义 IOperation 接口,声明一个 exec(BookList bookList) 方法。所有功能类(FindOperation、DelOperation…)都实现它。
Main.java 的菜单循环就变成:
operations[choice].exec(books);新增一个“按作者统计数量”功能?只写新类 AuthorCountOperation 实现接口,注册到数组里,Main 一行代码都不用动。
构造器也走封装通道,别绕过校验
Book 构造器如果直接给 this.name = name,那 new Book("", -5) 就合法了。正确做法是:
- 构造器里调用 this.setName(name) 和 this.setPrice(price)
- 所有校验逻辑只写在 set 方法里,一处维护,处处生效
哪怕只是控制台小项目,这种习惯一上来就养成,后面对接数据库、加日志、做权限拦截,骨架已经立住了。











