Java 进阶必修课:一文拆解面向对象(封装·继承·多态)

发布时间:2026/6/28 11:49:30
Java 进阶必修课:一文拆解面向对象(封装·继承·多态) 很多同学学完 Java 基础语法后写代码依然像在写“高级 C 语言”——满屏的 ​​static​​方法和零散的变量完全没有发挥出面向对象的威力。今天我们通过一个完整的业务案例 渐进式代码演化把面向对象的三大核心特性封装、继承、多态彻底串起来。文章不长但每一个代码片段都值得你停下来思考。一、封装不仅要“藏起来”还要“管起来”场景我们要做一个简单的员工管理系统。错误示范面向过程思维// 这样写name 和 age 在外面想怎么改就怎么改毫无安全感 class Employee { String name; int age; } // 使用时 Employee e new Employee(); e.age -10; // 年龄怎么能是负数代码毫无约束力正确姿势封装封装不仅仅是加 ​​private​​更重要的是提供受控的访问入口Getter/Setter并在入口处设立关卡。class Employee { // 1. 属性私有化隐藏内部实现 private String name; private int age; // 2. 提供公共的访问方法 public String getName() { return name; } public void setName(String name) { this.name name; // this 区分成员变量与参数 } public int getAge() { return age; } public void setAge(int age) { // 3. 在方法内部做逻辑校验封装业务规则 if (age 18 age 60) { this.age age; } else { throw new IllegalArgumentException(员工年龄必须在18-60岁之间); } } }​​http://www.wx-tong.com/​​​​private​​保证了数据的安全性。​​this.age​​明确了当前对象的属性避免了命名歧义。Setter 方法不再是简单的赋值而是包含了业务逻辑数据合法性检查。二、继承从“重复代码”到“抽象共性”现在需求变了公司不仅有普通员工​​Employee​​还有经理​​Manager​​。经理也是员工也有姓名年龄但他还多了一个“奖金”属性。笨办法Copy-Paste 代码。但这样维护起来是灾难。继承的办法提取共性建立层级。// 父类抽象出“员工”的共性 class Employee { private String name; private int age; // 构造方法 public Employee(String name, int age) { this.name name; this.age age; } // 共同的行为 public void work() { System.out.println(name 正在工作...); } // Getter/Setter 省略... } // 子类在员工的基础上扩展 class Manager extends Employee { private double bonus; // 经理特有的奖金 // 子类的构造方法 public Manager(String name, int age, double bonus) { // super调用父类的构造方法初始化共有属性 super(name, age); this.bonus bonus; } // 子类特有的方法 public void manage() { System.out.println(getName() 正在管理团队奖金 bonus); } } 代码解读​​extends​​建立了继承关系。​​super(name, age)​​是关键它显式调用了父类的构造器确保父类部分先被初始化。如果父类有无参构造这行代码甚至可以省略编译器会自动加但显式写出来是更好的习惯。子类自动拥有了父类的work()能力同时扩展了自己的manage()能力。三、多态编译看左边运行看右边这是面向对象最精彩的部分。假设我们有一个方法需要让所有员工开始工作。没有多态的写法糟糕public static void letThemWork(Employee e) { ... } public static void letThemWork(Manager m) { ... } // 每新增一个工种就要新增一个方法太麻烦有多态的写法优雅我们只需要一个接收父类​​Employee​​的方法却可以传入任意子类对象。// 1. 父类引用指向子类对象向上转型 Employee emp1 new Employee(张三, 25); Employee emp2 new Manager(李四, 35, 10000); // 多态的核心体现 // 2. 定义一个统一的方法 public static void letThemWork(Employee employee) { // 3. 运行时绑定到底执行谁的 work 方法 employee.work(); } // 调用 letThemWork(emp1); // 输出张三正在工作... letThemWork(emp2); // 输出李四正在工作...虽然是 Employee 引用但实际跑的是 Manager 继承来的逻辑​​Employee emp2 new Manager(...)​​​​http://www.wx-tong.com/​​这就是向上转型。编译器只看 ​​Employee​​​所以你不能直接用 ​​emp2.manage()​​除非强转。动态绑定虽然emp2的编译类型是Employee但运行时 JVM 知道它实际上是Manager。不过这里调用的是work()它没有被重写所以表现一致。四、方法重写多态的灵魂上面的例子还不够震撼因为 ​​work()​​没变。现实中经理的工作内容和员工肯定不一样。这就需要方法重写Override。class Employee { protected String name; // 改为 protected方便子类直接访问 public Employee(String name) { this.name name; } // 父类的通用工作方法 public void work() { System.out.println(name 正在处理基础事务...); } } class Manager extends Employee { public Manager(String name) { super(name); } // 重写父类方法Override 注解能帮助编译器检查错误 Override public void work() { // 可以在重写时调用父类原逻辑 // super.work(); System.out.println(name 正在制定战略和管理团队...); } } // 测试类 public class OfficeTest { public static void main(String[] args) { Employee staff1 new Employee(张三); Employee boss1 new Manager(李四); staff1.work(); // 输出张三正在处理基础事务... boss1.work(); // 关键点输出李四正在制定战略和管理团队... // 编译看左Employee有work运行看右实际执行Manager的work } } 代码解读​​Override​​这个注解不是必须的但强烈建议加上。如果方法签名写错比如写成wrk编译器会报错防止低级 Bug。​​super.work()​​在重写方法中可以用super调用父类的原方法实现逻辑的复用与增强。多态生效的条件继承 方法重写 父类引用指向子类对象。三者缺一不可。五、总结从代码看思想让我们把这段代码映射到面向对象的精髓上封装private属性和getter/setter构成了对象的“防御体系”保证了数据的完整性和业务的规范性。继承extends建立了is-a关系Manager is an Employee消除了冗余代码实现了代码的复用和功能的扩展。多态Employee boss new Manager()配合方法重写使得我们可以写出通用的代码letThemWork方法从容应对未来的变化比如新增CEO类无需修改该方法。最后的忠告多态虽然强大但也有代价。它牺牲了编译期的类型检查无法直接调用子类独有方法换取了运行期的灵活性。因此不要为了用多态而用多态只有当确实需要在“忽略具体类型关注通用行为”时多态才是最佳选择。