封装是控制数据变更权,通过private锁字段、setter校验联动、getter只读防篡改;继承是明确is-a契约复用,子类承诺实现父类行为;多态是隔离变化点与稳定点,新增实现不改旧代码。

直接说“封装就是 private + getter/setter,继承就是 extends,多态就是父类引用指向子类对象”,别人听完大概率还是不会用。真正讲清楚,得从“为什么需要”出发,再落到“怎么用才对”。下面这三块,是讲给开发者听时最实用、最容易被记住的讲法。
封装:不是为了加 private,而是为了控制谁能在什么时候改什么
别一上来就写 private 和 setXXX。先问一句:“如果 age 字段是 public,别人 new 一个 Student 后直接写 stu.age = -5,会发生什么?”——数据立刻失真,而且你根本拦不住。
封装的本质是建一道“访问闸门”:
- private 把字段锁死,只允许本类内部操作
- setter 是带安检的入口:可以校验(比如年龄 0–150)、可以触发联动(比如改了 price 就自动更新 lastModifiedTime)、可以打日志
- getter 是只读窗口:可以返回副本(防外部篡改 List)、可以做懒加载(第一次调用才计算)、可以统一格式化(比如把 timestamp 转成 yyyy-MM-dd)
一句话总结:封装不是藏代码,是把“数据变更权”收归类自己管。
立即学习“Java免费学习笔记(深入)”;
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
继承:不是为了多写几个 class,而是为了明确“谁复用了谁的契约”
很多人一看到 Animal → Dog → Poodle 就觉得是继承,但关键不在层级,而在语义是否成立:“Poodle 是一种 Dog,Dog 是一种 Animal”——这个 is-a 关系必须自然、稳定、无歧义。
讲继承时重点说清三件事:
- 子类不是“复制”父类,而是“承诺实现父类定义的行为契约”(比如 Animal 的 move() 方法,Dog 必须能跑,Fish 必须能游)
- 父类里用 protected 修饰的字段/方法,是专门留给子类“有限参与”的接口;private 则彻底不开放,避免子类误依赖
- 构造器不继承,但子类必须显式调用 super() —— 这是在强调:“我复用你的初始化逻辑,不是绕过它”
反例比正例更有说服力:比如把 “MySQLConnection” 和 “RedisClient” 都继承自 “DBClient”,就违背了 is-a,因为它们不是同一类东西,只是都跟数据打交道(该用组合,不是继承)。
多态:不是为了炫技,而是让新增功能不用改老代码
别只讲 Animal a = new Dog();要带场景讲:
- 假设你写了个支付系统,现在支持支付宝、微信、银行卡。如果每个渠道都 if (type == "alipay") { ... } else if (type == "wechat") { ... },那每加一个新渠道,就得打开这个长长的 if 块——这就是多态要解决的问题
- 正确做法:定义 Payment 接口,AlipayPay、WechatPay、CardPay 各自实现 pay() 方法;上层只依赖 Payment payment = getPayment(type); payment.pay();
- 这时候新增 ApplePay,只需写个新类实现接口,注册进工厂或配置里,原有调用代码一行都不用动
多态真正的价值,是把“变化点”(不同实现)和“稳定点”(统一调用)隔开。它不是语法糖,是应对需求迭代的防御性设计。

















