举例说说面向对象编程及其三大特性

💡 一则也许对你有用的小广告 🏆

欢迎飞飞程序员   ,你将获得:专属的实战项目(已更新的所有会员标识的项目都能学习) / 1v1 提问 / Java 学习路线 / PHP 学习路线 / 学习打卡 / 社群讨论

  • 正在进行中的项目:《FFBlog知识付费博客项目》 正在持续更新中,基于 Spring Boot 3.x + JDK 21...,点击查看 ;
  • 《从零开发:FFBlog知识付费博客项目(全栈开发)》 演示链接: https://ffblog.ffcxy.com/  ;

截止目前, 飞飞  正在疯狂爆肝实战项目,后续还会上新更多项目,目标是将所学知识开发成项目并且分享给大家,如知识付费系统, Ai系统, CMS系统,在线商城系统,等等 ,欢迎点击围观

这题考什么

  • 能不能用例子把概念说人话。这题是 Java 面试的开门题,面试官不指望你背定义,他想听你拿一个具体场景(比如 Animal/Dog/Cat、Order/支付)把封装、继承、多态讲明白。
  • 知不知道三大特性各自的边界。封装到底藏了什么、继承解决什么问题、多态的「同一接口不同实现」是编译期决定还是运行期决定,这几个点会追问。
  • 有没有踩过继承的坑。比如构造方法能不能继承、重载算不算多态、为什么实际开发里建议组合优于继承。

先说结论

面向对象就是把数据和操作数据的方法绑成一个对象,用对象之间的交互来组织程序;三大特性是封装(隐藏细节)、继承(复用与扩展)、多态(同一调用,不同行为)。

// 三句人话版
封装:把字段设成 private,只留 getter/setter 和方法给人用
继承:class Dog extends Animal,公共的东西抽到父类
多态:Animal a = new Dog(); a.sound();  // 调的是 Dog 的实现

封装:把细节关进类里

封装就是把对象的状态藏起来,只暴露该暴露的操作。字段用 private,外部想动它只能走你提供的方法,方法里可以加校验、加日志、改内部实现而不影响调用方。

public class BankAccount {
    private double balance;   // 藏起来,不让外面瞎改

    public void deposit(double amount) {
        if (amount <= 0) throw new IllegalArgumentException("金额必须为正");
        this.balance += amount;   // 改状态只能走我这条路
    }
    public double getBalance() {
        return balance;
    }
}

好处很实在:外部拿不到脏数据,内部把 double 换成 BigDecimal 也不用改调用方代码。面试里说「封装 = 属性私有 + 方法暴露 + 校验收口」就够了。

继承:公共的抽上去,子类只写差异

继承用 extends 表达 is-a 关系,父类放通用的字段和方法,子类复用并扩展。Java 只支持单继承,类不能多继承(多继承的歧义问题),想多重复用就用接口 implements。

public class Animal {
    protected String name;
    public Animal(String name) { this.name = name; }
    public void eat() { System.out.println(name + " 吃东西"); }
}

public class Dog extends Animal {
    public Dog(String name) { super(name); }   // 构造方法不继承,只能 super 调
    public void bark() { System.out.println(name + " 汪汪"); }
}

几个常被问的点:构造方法不参与继承,子类构造器第一行必须靠 super(...) 去调父类的;extends 会把父类的 protected 成员带进来;Object 是所有类的祖先。

多态:同一个调用,跑出不同行为

多态的典型姿势是父类引用指向子类对象,方法重写(override)之后,同一行 a.sound() 在运行期决定执行哪个实现,这叫动态绑定。

Animal dog = new Dog("旺财");
Animal cat = new Cat("咪咪");

dog.sound();   // 旺财: 汪汪
cat.sound();   // 咪咪: 喵喵

底层原理值得多说一句:编译期编译器只看引用类型 Animal,检查你有没有 sound() 这个方法;运行期 JVM 看对象实际类型,通过虚方法表(vtable)找到 Dog 或 Cat 的实现,用 invokevirtual 调过去。所以方法重写才有多态,字段和静态方法没有(它们是静态绑定)。

多态最实用的地方是可扩展:要加个 Bird,新建子类重写 sound(),调用方那堆 for (Animal a : list) a.sound(); 一行都不用改。

想调子类独有的方法(比如 Dog 的 bark()),得先向下转型 ((Dog) a).bark(),最好配 instanceof 判断,不然容易 ClassCastException。

面试高频追问

封装和「数据隐藏」是一回事吗? 差不多,封装是手段,隐藏是结果:访问修饰符收口访问,方法收口行为,两者合起来才叫封装,不只是把字段标 private。

重载(overload)算多态吗? 严格说三大特性里的多态指运行时动态绑定(方法重写)。重载是编译期按参数列表挑方法,属于静态多态,说「广义算、狭义不算」比较稳。

构造方法能被继承吗? 不能。构造方法跟类名绑定,不参与继承,子类只能用 super(...) 显式调用父类构造。

父类引用能直接调子类独有方法吗? 不能,编译期按引用类型检查,看不到 Dog 独有的 bark()。要么改引用类型,要么 instanceof 后强转。

Java 支持多继承吗? 类不支持,会遇到菱形继承的二义性;接口可以 implements 多个,方法默认实现冲突时用 Xxx.super.method() 指定。

继承既然好用,为什么说「优先组合」? 继承是紧耦合,父类改了子类全遭殃,而且 Java 单继承限制了灵活性。组合(把别的对象当字段用)更松、更灵活,ArrayList 内部包个数组就是典型的组合思路。

多态是怎么实现的? 方法重写 + 虚方法表。JVM 为每个类生成一张方法表,运行时按对象实际类型的 vtable 定位实现,配合 invokevirtual 完成分派;静态方法和 final 方法可以静态绑定,效率更高。

怎么记

记一句话就够:封装管「不让乱动」,继承管「不用重写」,多态管「不用改代码也能扩展」。再往上一层:封装解决安全性,继承解决复用,多态解决扩展性——面试官问「三大特性各自解决了什么问题」,答这三句基本满分。

最后编辑于 2026-10-12 19:15:00
上一篇 break和continue的区别?
已是最后一篇

全部评论(0)

头像
😃 😁 😅 😂 😍 😜 😝 🤑 🥵 🥰 😙 😎 😵 😭 😱 😖 🥳 👽 🙈 🤡 😤 💣 💯 💢 ❤️ 👍 👏 👋 👌 🤏 🙏
还没有任何评论哟~
微信扫一扫
微信二维码
微信客服
QQ 咨询
QQ二维码
工作日 9:00 - 18:00 在线
QQ客服
在线工单
提交问题工单,我们会尽快回复处理。
提交工单
在线工单
目录