第 8 章 · 面向对象(下)

8.1 类的继承

子类通过 extends 继承父类的字段与方法,实现代码复用与“is-a”关系。

class Animal {
    void eat() { System.out.println("eating"); }
}
class Dog extends Animal {
    void bark() { System.out.println("wang"); }
}
  • Java 只支持单继承(一个类只能有一个父类),Object 是所有类的最终父类。
  • 方法重写(Override):子类用 @Override 重写父类方法,返回类型、方法名、参数须一致。
  • super:调用父类构造(super(...))或父类被重写的方法(super.eat())。

对比:C++ 支持多继承(易引发菱形问题),Java 用“单继承 + 多接口”规避;Python 支持多继承(MRO 解析)。

8.2 final 关键字

  • final 修饰类:不能被继承。
  • final 修饰方法:不能被重写。
  • final 修饰变量:值不可变(基本类型值不变,引用类型引用不变、对象内容可改)。

8.3 抽象类与接口

抽象类abstract 修饰,可有抽象方法(无方法体),子类必须实现;不能被实例化。

abstract class Shape {
    abstract double area();      // 抽象方法
    void print() { System.out.println("shape"); }
}

接口:一组抽象方法的规范,JDK 8+ 可有默认方法和静态方法。

interface Flyable {
    void fly();                    // 隐式 public abstract
    default void land() { System.out.println("landing"); }
}
class Bird implements Flyable {
    public void fly() { System.out.println("flying"); }
}
  • 一个类可实现多个接口implements A, B),弥补单继承限制。
  • 抽象类偏“是什么”(is-a),接口偏“能做什么”(can-do)。

对比:C++ 的“接口”靠纯虚函数 + 多继承实现;Python 有抽象基类(abc)和鸭子类型(duck typing)——只要对象有 fly() 方法就能用,不必声明实现接口。

8.4 多态

父类引用指向子类对象,运行时根据实际类型调用对应方法(动态绑定):

Animal a = new Dog();
a.eat();               // 调用 Dog 重写后的 eat
  • 多态让代码面向抽象编程,扩展新子类无需改动调用方。
  • 对象类型转换:向上转型(子→父)自动;向下转型(父→子)需强转,用 instanceof 判断。
  • Object 类toString()equals()hashCode() 常被重写。

8.5 异常

异常是程序运行期错误的对象表示,用 try/catch/finally 处理,避免程序崩溃。

try {
    int r = 10 / 0;
} catch (ArithmeticException e) {
    System.out.println("除零错误");
} finally {
    System.out.println("总会执行");
}
  • 受检异常(checked):编译期强制处理(需 catch 或 throws),如 IOException
  • 非受检异常(unchecked)RuntimeException 及其子类,如 NullPointerException
  • throws 声明方法可能抛出的异常;可自定义异常类继承 Exception

对比:C 用错误码 + errno(易被忽略);C++ 有异常但非强制;Python 异常全面但不区分受检/非受检。Java 的受检异常强制调用方处理,健壮但被诟病啰嗦。

8.6 包与访问控制

  • 包(package):组织类、避免命名冲突,对应目录结构;import 引入其他包的类。
  • 访问修饰符(从窄到宽):private < 默认(同包)< protected(同包+子类)< public

8.7 与其他语言对比

特性JavaC++Python
继承单继承 + 多接口多继承多继承
多态虚方法(默认动态绑定)virtual 才动态绑定全部动态绑定
异常强制 checked可选全部运行时
访问控制4 级3 级 + friend约定(下划线)

关键差异:Java 默认方法就是虚方法(动态绑定),C++ 默认静态绑定、需显式 virtual;这决定了 Java 天然面向多态。