Java中的方法重写需要注意什么_方法重写规则与常见问题解析

Java方法重写需满足:签名完全一致(含方法名、参数列表)、访问权限不更严格、返回类型协变兼容、检查型异常不扩大;static、final、private方法不可重写。

Java中方法重写(Override)是面向对象多态性的核心机制,但若不遵守规则,轻则编译失败,重则引发运行时逻辑错误。关键在于:子类方法必须与父类被重写方法具有相同的签名(方法名、参数列表),且访问权限不能更严格,返回类型需协变兼容,异常声明不能抛出新或更宽泛的检查型异常。

方法签名必须完全一致

重写要求子类方法名、参数个数、参数类型顺序、参数类型(含泛型擦除后)与父类方法严格一致。注意:

  • 仅返回类型不同不算重写,而是编译错误(除非是协变返回类型,见下条)
  • 参数名称可以不同,但类型和顺序不可变;int aint b 视为相同参数
  • 可变参数(...args)与数组参数(int[] args)在擦除后等价,二者互为重写关系,但混用易引发歧义,应避免

返回类型支持协变,但有明确限制

从Java 5起允许子类重写方法时使用更具体的返回类型(协变返回),前提是该类型是父类方法返回类型的子类型:

  • 父类方法返回 Object,子类可返回 String 或自定义类(如 User
  • 但不能返回无关类型(如 Integer 重写返回 String 的方法)
  • 基本类型和其包装类之间不构成协变关系(intInteger 不能互相重写)

访问修饰符不能更严格,异常声明不能扩大

子类重写方法的可见性只能等于或大于父类方法(private 方法不可被重写):

  • 父类是 protected,子类可用 public,但不能用 private 或包级(默认)
  • 关于异常:子类方法可抛出更少或更具体的检查型异常(IOExceptionFileNotFoundException),但不能新增或抛出更宽泛的检查型异常(如父类没声明异常,子类不能加 th

    rows Exception
  • 运行时异常(RuntimeException 及其子类)不受此限,可自由添加或删除

常见误判与陷阱

这些情况看似像重写,实为重载或编译错误:

  • static 方法不能被重写(可被隐藏),子类同名静态方法与父类静态方法构成“隐藏”,调用取决于引用类型而非实际类型
  • final 方法不能被重写,编译直接报错
  • 父类方法为 private,子类中同名方法只是新定义,与重写无关(因为 private 方法不可见、不可继承)
  • 忘记加 @Override 注解:虽非强制,但强烈建议添加——它让编译器帮你校验是否真正在重写,避免拼写错误(如 hashcode() 写成 hashCode())导致意外重载