目录

面试速答

重载(Overload):方法名相同,参数列表不同。编译器根据实参在编译期选择方法,属于静态绑定。

重写(Override):子类重新实现父类的实例方法。调用哪个版本由对象的运行时类型决定,属于动态绑定。

一句话记忆:重载看参数,编译期确定;重写看对象,运行期确定。

重载与重写对比

对比项 方法重载 方法重写
方法名 必须相同 必须相同
参数列表 必须不同 必须相同
返回值 可以不同,但不能单独作为重载依据 相同或为父类返回类型的子类
访问权限 没有特殊限制 不能比父类方法更严格
检查异常 没有特殊限制 不能声明更宽泛的新检查异常
绑定时机 编译期 运行期
多态类型 编译时多态 运行时多态

方法重载

核心规则

重载要求方法名相同、参数列表不同。参数的个数、类型或顺序不同都可以构成重载。

返回值和参数名不参与重载区分。只修改返回值或参数名,会因为方法签名重复而编译失败。

class Calculator {
    int add(int a, int b) {
        return a + b;
    }

    long add(long a, long b) {
        return a + b;
    }

    int add(int a, int b, int c) {
        return a + b + c;
    }
}

构造方法可以重载,因为同一个类可以提供多组不同的构造参数。

方法重写

核心规则

  • 父子类方法的名称和参数列表必须相同。
  • 返回类型必须相同,或者是父类方法返回类型的子类,即协变返回类型。
  • 子类方法的访问权限不能更严格。
  • 子类方法不能声明比父类方法更宽泛的新检查异常,运行时异常不受该限制。
  • 建议始终使用 @Override,让编译器帮助检查。
class Animal {
    Animal create() {
        return new Animal();
    }

    void speak() {
        System.out.println("Animal");
    }
}

class Dog extends Animal {
    @Override
    Dog create() { // 协变返回类型
        return new Dog();
    }

    @Override
    void speak() {
        System.out.println("Dog");
    }
}

Animal animal = new Dog();
animal.speak(); // Dog

哪些方法不能重写

方法类型 结论
private 对子类不可见,不参与继承,因此不能重写
final 可以继承,但明确禁止子类重写
static 子类同签名静态方法是隐藏,不是重写,调用在编译期绑定
构造方法 不会被继承,可以重载,不能重写

static 方法隐藏

class Parent {
    static void staticMethod() {
        System.out.println("Parent static");
    }

    void instanceMethod() {
        System.out.println("Parent instance");
    }
}

class Child extends Parent {
    static void staticMethod() {
        System.out.println("Child static");
    }

    @Override
    void instanceMethod() {
        System.out.println("Child instance");
    }
}

Parent value = new Child();
value.staticMethod();   // Parent static:看引用类型
value.instanceMethod(); // Child instance:看对象类型

易错点总结

  • 只改变返回值不能构成重载。
  • 子类方法参数不同时是重载,不是重写。
  • 字段只能被遮蔽,不能被重写。
  • 静态方法是隐藏,实例方法才能通过重写实现运行时多态。
  • 没有写 @Override 时,一个参数类型的小错误可能让本想重写的方法变成重载。

参考资料