在Java中,子类重写(Override)父类方法需要遵循一系列规则,这些规则确保了面向对象的多态性能够正确实现。主要要求如下:
1. 方法签名必须完全一致
-
方法名、参数列表(参数类型、顺序、个数)必须与父类方法完全相同。
若参数列表不同,即使方法名相同,也属于“重载(Overload)”而非“重写”。示例:
class Parent { public void print(int a) { ... } // 父类方法 } class Child extends Parent { // 正确:方法名和参数列表与父类一致(重写) @Override public void print(int a) { ... } // 错误:参数列表不同(这是重载,不是重写) // @Override // 加注解会编译报错 public void print(String a) { ... } }
2. 返回值类型需兼容
-
若父类方法返回基本类型,子类重写的方法必须返回相同的基本类型。
-
若父类方法返回引用类型,子类方法可以返回该类型的子类(称为“协变返回类型”)。
示例:
class Parent { public Number getValue() { return 0; } // 父类返回Number } class Child extends Parent { // 正确:返回Number的子类(Integer) @Override public Integer getValue() { return 1; } }
3. 访问修饰符不能更严格
-
子类重写的方法的访问权限不能比父类方法更严格(可以相同或更宽松)。
权限等级(从宽到严):public > protected > default(无修饰符) > private。示例:
class Parent { protected void doSomething() { ... } // 父类为protected } class Child extends Parent { // 正确:权限更宽松(public > protected) @Override public void doSomething() { ... } // 错误:权限更严格(private < protected) // @Override // private void doSomething() { ... } }
4. 异常声明需受限
-
子类重写的方法不能抛出比父类方法更多、更广泛的检查型异常(Checked Exception)。
- 可以不抛异常,或抛出父类异常的子类异常,或抛出更少的异常。
- 运行时异常(Unchecked Exception,如
NullPointerException)不受此限制。
示例:
import java.io.IOException; import java.io.FileNotFoundException; class Parent { public void read() throws IOException { ... } // 父类抛IOException } class Child extends Parent { // 正确:抛出IOException的子类(更具体) @Override public void read() throws FileNotFoundException { ... } // 错误:抛出比IOException更广泛的异常(如Exception) // @Override // public void read() throws Exception { ... } }
5. 特殊方法不能被重写
- 私有方法(private):父类的
private方法对子类不可见,子类若定义同名方法,属于新方法(非重写)。 - 静态方法(static):静态方法属于类而非对象,子类若定义同名静态方法,属于“隐藏(Hide)”而非重写(调用时取决于引用的类型,而非对象实际类型)。
- 被final修饰的方法:
final方法是“不可修改的”,子类不能重写。 - 构造方法:构造方法名与类名一致,子类无法重写父类构造方法(但可以通过
super()调用)。
6. 必须使用@Override注解(推荐)
- 虽然不是强制要求,但显式添加
@Override注解可以让编译器检查是否符合重写规则,避免意外错误(如拼写错误、参数不一致等)。
总结:重写的核心是“保持方法签名兼容,权限不收紧,异常不扩大”,同时遵循特殊方法的限制,以确保多态性的正确运行。
在Java中,重写(Override) 和重载(Overload) 是两个容易混淆但本质不同的概念,核心区别体现在定义、用途和规则上。以下是详细对比:
1. 定义与核心目的
| 特性 | 重写(Override) | 重载(Overload) |
|---|---|---|
| 定义 | 子类对父类中同名、同参数的方法进行重新实现 | 同一个类中,方法名相同但参数列表不同的多个方法 |
| 核心目的 | 实现多态:让子类拥有自己特有的行为逻辑 | 方便调用:用同一方法名处理不同参数的场景 |
2. 关键区别
(1)发生范围不同
- 重写:必须发生在父子类继承关系中(子类重写父类的方法)。
- 重载:发生在同一个类中(也包括子类继承的父类方法在子类中被重载的情况,但本质是同一类内)。
(2)方法签名要求不同
-
方法签名:由“方法名 + 参数列表(参数类型、顺序、个数)”组成。
- 重写:要求方法签名完全相同(方法名、参数列表必须与父类一致)。
- 重载:要求方法名相同,但参数列表必须不同(如参数类型不同、个数不同、顺序不同)。
// 重写示例 class Parent { public void test(int a) {} // 父类方法 } class Child extends Parent { @Override public void test(int a) {} // 重写:签名与父类完全相同 } // 重载示例 class MyClass { public void test(int a) {} // 方法1 public void test(String b) {} // 重载:参数类型不同 public void test(int a, String b) {} // 重载:参数个数不同 }
(3)返回值要求不同
- 重写:
- 若父类方法返回基本类型,子类必须返回相同的基本类型;
- 若父类返回引用类型,子类可返回该类型的子类(协变返回类型)。
- 重载:对返回值无要求(可以相同,也可以不同)。
(4)访问修饰符与异常的限制不同
- 重写:
- 子类方法的访问权限不能比父类更严格(如父类是
protected,子类可改为public,但不能改为private); - 子类方法不能抛出比父类更广泛的检查型异常(可抛出更少或更具体的异常)。
- 子类方法的访问权限不能比父类更严格(如父类是
- 重载:对访问修饰符和异常无限制(可任意修改)。
(5)与多态的关系不同
- 重写:是实现运行时多态的核心(调用方法时,根据对象的实际类型执行对应子类的实现)。
- 重载:是编译时多态(调用时,编译器根据参数类型匹配对应的方法)。
3. 总结表格
| 对比维度 | 重写(Override) | 重载(Overload) |
|---|---|---|
| 发生范围 | 父子类之间 | 同一个类中 |
| 方法签名 | 完全相同(名+参数) | 名相同,参数列表不同 |
| 返回值 | 基本类型必须相同;引用类型可协变 | 无限制 |
| 访问修饰符 | 不能更严格 | 无限制 |
| 异常处理 | 不能抛出更广泛的检查异常 | 无限制 |
| 多态类型 | 运行时多态 | 编译时多态 |
| 注解 | 推荐使用@Override验证 | 无专用注解 |
通过以上对比可以看出:重写是“父子类间的方法覆盖”,核心是多态;重载是“同类内的方法复用”,核心是便捷性。
947

被折叠的 条评论
为什么被折叠?



