首页 > 应用开发 > IT综合 > 方法重写深度解析:规则、原理与重载对比
# 方法重写深度解析:规则、原理与重载对比
## 方法重写的基本规则与要求
方法重写是面向对象多态性的核心实现机制,必须遵循严格的语法规则。
```java
// 父类定义
public class Animal {
protected String name;
protected int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
// 可重写的方法
public void makeSound() {
System.out.println(name + " 发出声音");
}
// 带返回值的方法
public String getDescription() {
return name + ",年龄:" + age;
}
// 带参数的方法
public void eat(String food) {
System.out.println(name + " 吃 " + food);
}
// 受保护的方法
protected void sleep() {
System.out.println(name + " 正在睡觉");
}
// 不可重写的方法
public final void breathe() {
System.out.println(name + " 正在呼吸");
}
// 静态方法 - 不能重写,只能隐藏
public static void animalInfo() {
System.out.println("这是动物类");
}
}
// 子类正确重写示例
public class Dog extends Animal {
private String breed;
public Dog(String name, int age, String breed) {
super(name, age); // 必须调用父类构造器
this.breed = breed;
}
// 正确重写:方法签名完全相同
@Override
public void makeSound() {
System.out.println(name + " 汪汪叫");
}
// 正确重写:返回值类型可以是父类返回值的子类(协变返回类型)
@Override
public String getDescription() {
return super.getDescription() + ",品种:" + breed;
}
// 正确重写:访问权限可以更宽松
@Override
public void sleep() { // 父类是protected,子类可以是public
System.out.println(name + " 在狗窝睡觉");
}
// 调用父类被重写的方法
public void makeSoundAndSuper() {
super.makeSound(); // 调用父类的makeSound
this.makeSound(); // 调用子类的makeSound
}
// 无法重写final方法
// public void breathe() { } // 编译错误
// 方法隐藏(不是重写)
public static void animalInfo() {
System.out.println("这是狗类");
}
}
// 重写规则验证
public class OverrideRulesValidator {
public void validateRules() {
Dog dog = new Dog("小黑", 3, "金毛");
// 多态调用:运行时确定实际方法
Animal animalRef = dog;
animalRef.makeSound(); // 调用Dog的makeSound
// 静态方法调用:编译时确定
animalRef.animalInfo(); // 调用Animal的animalInfo(方法隐藏)
Dog.animalInfo(); // 调用Dog的animalInfo
// 协变返回类型演示
String description = dog.getDescription();
System.out.println(description);
// 访问权限测试
dog.sleep(); // 可以调用,因为Dog中sleep是public
// final方法测试
dog.breathe(); // 调用Animal的final方法
}
}
```
## 方法重写的底层实现原理
理解JVM如何实现方法重写对于深入掌握多态机制至关重要。
```java
// 分析JVM方法表(vtable)的实现
public class OverrideMechanism {
// 简单的继承层次
static class Base {
public void method1() {
System.out.println("Base.method1");
}
public void method2() {
System.out.println("Base.method2");
}
public final void method3() {
System.out.println("Base.method3 (final)");
}
public static void staticMethod() {
System.out.println("Base.staticMethod");
}
}
static class Derived extends Base {
@Override
public void method2() {
System.out.println("Derived.method2");
}
public void method4() {
System.out.println("Derived.method4");
}
// 这是方法隐藏,不是重写
public static void staticMethod() {
System.out.println("Derived.staticMethod");
}
}
static class DeepDerived extends Derived {
@Override
public void method2() {
System.out.println("DeepDerived.method2");
}
@Override
public void method1() {
System.out.println("DeepDerived.method1");
}
}
// 演示JVM方法表概念
public void explainVTable() {
System.out.println("=== JVM方法表(vtable)概念演示 ===");
// 每个类都有自己的方法表
System.out.println("Base类的vtable包含:");
System.out.println(" method1 -> Base.method1");
System.out.println(" method2 -> Base.method2");
System.out.println(" method3 -> Base.method3 (final)");
System.out.println(" staticMethod -> Base.staticMethod");
System.out.println("\nDerived类的vtable包含:");
System.out.println(" method1 -> Base.method1 (继承)");
System.out.println(" method2 -> Derived.method2 (重写)");
System.out.println(" method3 -> Base.method3 (final,继承)");
System.out.println(" method4 -> Derived.method4 (新增)");
System.out.println(" staticMethod -> Derived.staticMethod (隐藏)");
System.out.println("\nDeepDerived类的vtable包含:");
System.out.println(" method1 -> DeepDerived.method1 (重写)");
System.out.println(" method2 -> DeepDerived.method2 (重写)");
System.out.println(" method3 -> Base.method3 (继承)");
System.out.println(" method4 -> Derived.method4 (继承)");
// 演示对象在内存中的方法调用
Base obj1 = new Base();
Base obj2 = new Derived();
Base obj3 = new DeepDerived();
System.out.println("\n=== 动态绑定演示 ===");
System.out.print("obj1.method2(): ");
obj1.method2(); // 调用Base.method2
System.out.print("obj2.method2(): ");
obj2.method2(); // JVM查找obj2实际类型的方法表,调用Derived.method2
System.out.print("obj3.method2(): ");
obj3.method2(); // JVM查找obj3实际类型的方法表,调用DeepDerived.method2
// final方法使用静态绑定
System.out.println("\n=== final方法静态绑定 ===");
obj3.method3(); // 编译时确定调用Base.method3
// 静态方法也是静态绑定
System.out.println("\n=== 静态方法绑定 ===");
obj3.staticMethod(); // 编译时确定调用Base.staticMethod
Derived.staticMethod(); // 调用Derived.staticMethod
}
// 通过反射观察方法信息
public void examineWithReflection() {
try {
Class<?> baseClass = Base.class;
Class<?> derivedClass = Derived.class;
Class<?> deepDerivedClass = DeepDerived.class;
System.out.println("\n=== 反射分析方法 ===");
// 获取Base类的方法
System.out.println("Base类的方法:");
for (java.lang.reflect.Method method : baseClass.getDeclaredMethods()) {
System.out.println(" " + method);
}
// 获取Derived类的方法
System.out.println("\nDerived类的方法:");
for (java.lang.reflect.Method method : derivedClass.getDeclaredMethods()) {
System.out.println(" " + method);
}
// 检查是否重写了特定方法
java.lang.reflect.Method baseMethod2 = baseClass.getMethod("method2");
java.lang.reflect.Method derivedMethod2 = derivedClass.getMethod("method2");
System.out.println("\n方法重写检查:");
System.out.println("Base.method2: " + baseMethod2);
System.out.println("Derived.method2: " + derivedMethod2);
System.out.println("是否重写: " +
(baseMethod2.getDeclaringClass() != derivedMethod2.getDeclaringClass()));
} catch (Exception e) {
e.printStackTrace();
}
}
// 性能分析:虚方法调用开销
public void analyzePerformance() {
final int ITERATIONS = 10000000;
// 静态绑定(final方法)
Base base = new Base();
long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
base.method3(); // final方法,静态绑定
}
long staticTime = System.nanoTime() - start;
// 动态绑定(虚方法)
Base poly = new Derived();
start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
poly.method2(); // 虚方法,动态绑定
}
long dynamicTime = System.nanoTime() - start;
System.out.println("\n=== 性能对比 ===");
System.out.println("静态绑定(final方法)耗时: " + staticTime / 1000000 + "ms");
System.out.println("动态绑定(虚方法)耗时: " + dynamicTime / 1000000 + "ms");
System.out.println("性能差异比: " +
String.format("%.2f", (double)dynamicTime / staticTime));
// JVM优化:内联缓存
System.out.println("\n=== JVM优化 ===");
System.out.println("1. 内联缓存(Inline Cache):");
System.out.println(" JVM会缓存虚方法调用的目标方法");
System.out.println(" 如果连续多次调用都命中同一方法,JVM会进行优化");
System.out.println("2. 逃逸分析(Escape Analysis):");
System.out.println(" 如果对象不会逃逸出方法,JVM可能进行栈分配和标量替换");
System.out.println("3. 分层编译(Tiered Compilation):");
System.out.println(" JVM会根据方法调用频率进行不同级别的编译优化");
}
// 测试
public static void main(String[] args) {
OverrideMechanism demo = new OverrideMechanism();
demo.explainVTable();
demo.examineWithReflection();
demo.analyzePerformance();
}
}
```
## 方法重写与重载的详细对比
理解重写(Override)和重载(Overload)的根本区别。
```java
// 重写与重载对比示例
public class OverrideVsOverload {
// 父类
static class Calculator {
// 方法1:将被重写
public int calculate(int a, int b) {
System.out.println("Calculator.calculate(int, int)");
return a + b;
}
// 方法2:重载方法
public double calculate(double a, double b) {
System.out.println("Calculator.calculate(double, double)");
return a + b;
}
// 方法3:重载方法
public int calculate(int a, int b, int c) {
System.out.println("Calculator.calculate(int, int, int)");
return a + b + c;
}
// 方法4:重载方法(不同参数类型)
public String calculate(String a, String b) {
System.out.println("Calculator.calculate(String, String)");
return a + b;
}
}
// 子类
static class AdvancedCalculator extends Calculator {
// 重写父类方法
@Override
public int calculate(int a, int b) {
System.out.println("AdvancedCalculator.calculate(int, int) - 重写");
return a * b; // 改为乘法
}
<"uou.j9k5.org.cn"><"yty.j9k5.org.cn"><"asa.j9k5.org.cn">
// 重载方法(子类新增)
public double calculate(double a, double b, double c) {
System.out.println("AdvancedCalculator.calculate(double, double, double) - 重载");
return a * b * c;
}
// 重载父类方法(参数类型不同)
public int calculate(int a, double b) {
System.out.println("AdvancedCalculator.calculate(int, double) - 重载");
return (int)(a * b);
}
}
// 对比分析
public void demonstrateDifferences() {
System.out.println("=== 重写(Override)特性 ===");
System.out.println("1. 发生在继承关系中");
System.out.println("2. 方法签名必须完全相同(方法名+参数列表)");
System.out.println("3. 访问权限不能更严格");
System.out.println("4. 返回类型可以相同或是协变类型");
System.out.println("5. 运行时多态,基于对象实际类型");
System.out.println("\n=== 重载(Overload)特性 ===");
System.out.println("1. 发生在同一类中(或父子类间)");
System.out.println("2. 方法名相同,参数列表必须不同");
System.out.println("3. 返回类型可以不同");
System.out.println("4. 访问权限可以不同");
System.out.println("5. 编译时多态,基于引用类型和参数类型");
System.out.println("\n=== 实际演示 ===");
Calculator basic = new Calculator();
AdvancedCalculator advanced = new AdvancedCalculator();
Calculator polyRef = new AdvancedCalculator(); // 向上转型
System.out.println("\n1. 重写演示:");
System.out.print("basic.calculate(3, 4): ");
System.out.println(basic.calculate(3, 4)); // 7
System.out.print("advanced.calculate(3, 4): ");
System.out.println(advanced.calculate(3, 4)); // 12(重写为乘法)
System.out.print("polyRef.calculate(3, 4): ");
System.out.println(polyRef.calculate(3, 4)); // 12(多态调用,运行时确定)
System.out.println("\n2. 重载演示:");
System.out.print("basic.calculate(3.0, 4.0): ");
System.out.println(basic.calculate(3.0, 4.0)); // 7.0
System.out.print("basic.calculate(3, 4, 5): ");
System.out.println(basic.calculate(3, 4, 5)); // 12
System.out.print("advanced.calculate(3.0, 4.0, 5.0): ");
System.out.println(advanced.calculate(3.0, 4.0, 5.0)); // 60.0
System.out.print("advanced.calculate(3, 4.5): ");
System.out.println(advanced.calculate(3, 4.5)); // 13
System.out.println("\n3. 编译时类型 vs 运行时类型:");
System.out.println("polyRef的编译时类型: " + polyRef.getClass().getSimpleName());
System.out.println("polyRef的运行时类型: " + polyRef.getClass().getSimpleName());
// 重载在编译时确定
System.out.print("polyRef.calculate(3.0, 4.0): ");
System.out.println(polyRef.calculate(3.0, 4.0)); // 调用Calculator版本
// 尝试调用子类特有的重载方法(编译错误)
// polyRef.calculate(3.0, 4.0, 5.0); // 编译错误
// 需要向下转型
if (polyRef instanceof AdvancedCalculator) {
AdvancedCalculator casted = (AdvancedCalculator) polyRef;
System.out.print("转型后调用特有重载: ");
System.out.println(casted.calculate(3.0, 4.0, 5.0));
}
}
// 复杂场景分析
public void complexScenarios() {
System.out.println("\n=== 复杂场景分析 ===");
class A {
public void process(Number n) {
System.out.println("A.process(Number)");
}
}
class B extends A {
// 这是重载还是重写?
public void process(Integer i) {
System.out.println("B.process(Integer)");
}
// 明确的重写
@Override
public void process(Number n) {
System.out.println("B.process(Number) - 重写");
}
}
A a = new A();
B b = new B();
A ab = new B();
Number num = 10;
Integer integer = 10;
System.out.println("1. 参数类型匹配优先级:");
a.process(num); // A.process(Number)
a.process(integer); // A.process(Number) - Integer自动装箱为Number
System.out.println("\n2. 子类中的重载:");
b.process(num); // B.process(Number) - 重写版本
b.process(integer); // B.process(Integer) - 更精确的匹配
System.out.println("\n3. 多态调用中的重载解析:");
ab.process(num); // B.process(Number) - 运行时多态
ab.process(integer); // B.process(Number) - 编译时根据引用类型A解析
System.out.println("\n结论:");
System.out.println("- process(Integer)是B类新增的重载方法");
System.out.println("- 重载在编译时根据引用类型和参数类型解析");
System.out.println("- 重写在运行时根据对象实际类型解析");
}
// 测试
public static void main(String[] args) {
OverrideVsOverload demo = new OverrideVsOverload();
demo.demonstrateDifferences();
demo.complexScenarios();
}
}
```
## @Override注解的重要性
@Override注解不仅是语法糖,更是重要的代码质量保证工具。
```java
// @Override注解的深度分析
public class OverrideAnnotationAnalysis {
// 没有使用@Override的问题
class ProblematicBase {
public void process(String data) {
System.out.println("Base.process: " + data);
}
public void calculate(int x, int y) {
System.out.println("Base.calculate: " + (x + y));
}
}
class ProblematicDerived extends ProblematicBase {
// 意图重写process,但拼写错误
public void proces(String data) { // 缺少's',实际是新方法
System.out.println("Derived.proces: " + data);
}
// 意图重写calculate,但参数类型错误
public void calculate(double x, double y) { // 参数类型不同,实际是重载
System.out.println("Derived.calculate: " + (x * y));
}
}
// 正确使用@Override
class SafeBase {
public void process(String data) {
System.out.println("SafeBase.process: " + data);
}
public void calculate(int x, int y) {
System.out.println("SafeBase.calculate: " + (x + y));
}
}
class SafeDerived extends SafeBase {
@Override
// public void proces(String data) { // 编译错误:方法未重写
// System.out.println("SafeDerived.proces: " + data);
// }
public void process(String data) { // 正确拼写
System.out.println("SafeDerived.process: " + data);
}
@Override
// public void calculate(double x, double y) { // 编译错误:方法未重写
// System.out.println("SafeDerived.calculate: " + (x * y));
// }
public void calculate(int x, int y) { // 正确重写
System.out.println("SafeDerived.calculate: " + (x * y));
}
}
// 接口实现中的@Override
interface DataProcessor {
void process(String data);
default void validate(String data) {
if (data == null) {
throw new IllegalArgumentException("数据不能为空");
}
}
}
class FileProcessor implements DataProcessor {
@Override
public void process(String data) {
System.out.println("文件处理器处理: " + data);
}
@Override // 也可以用于重写默认方法
public void validate(String data) {
DataProcessor.super.validate(data); // 调用接口默认方法
if (data.length() > 1000) {
throw new IllegalArgumentException("数据过长");
}
}
}
// 抽象类中的@Override
abstract class AbstractProcessor {
public abstract void process(String data);
protected void log(String message) {
System.out.println("日志: " + message);
}
}
class ConcreteProcessor extends AbstractProcessor {
@Override
public void process(String data) {
log("开始处理: " + data);
System.out.println("处理数据: " + data);
}
@Override // 也可以重写具体方法
protected void log(String message) {
System.out.println("[INFO] " + java.time.LocalDateTime.now() + " " + message);
}
}
// 协变返回类型中的@Override
class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public Animal clone() throws CloneNotSupportedException {
return new Animal(this.name);
}
}
class Dog extends Animal {
private String breed;
public Dog(String name, String breed) {
super(name);
this.breed = breed;
}
@Override
public Dog clone() throws CloneNotSupportedException { // 协变返回类型
Dog cloned = (Dog) super.clone();
cloned.breed = this.breed;
return cloned;
}
}
// 演示@Override的重要性
public void demonstrateImportance() {
System.out.println("=== @Override注解的重要性 ===");
System.out.println("\n1. 错误案例演示:");
ProblematicBase pb = new ProblematicDerived();
pb.process("测试"); // 调用Base.process,不是预期的Derived.process
pb.calculate(2, 3); // 调用Base.calculate(2,3) = 5,不是预期的乘法
ProblematicDerived pd = new ProblematicDerived();
pd.proces("测试"); // 调用错误拼写的方法
pd.calculate(2.0, 3.0); // 调用重载方法,2.0*3.0=6.0
System.out.println("\n2. 正确案例演示:");
SafeBase sb = new SafeDerived();
sb.process("测试"); // 正确调用Derived.process
sb.calculate(2, 3); // 正确调用Derived.calculate,2*3=6
System.out.println("\n3. 接口和抽象类中的使用:");
DataProcessor processor = new FileProcessor();
processor.process("接口数据");
AbstractProcessor abstractProc = new ConcreteProcessor();
abstractProc.process("抽象类数据");
System.out.println("\n4. 协变返回类型:");
try {
Dog original = new Dog("小黑", "金毛");
Dog cloned = original.clone();
System.out.println("克隆狗: " + cloned.name + ", 品种: " + cloned.breed);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println("\n=== @Override的最佳实践 ===");
System.out.println("1. 重写任何方法时都使用@Override注解");
System.out.println("2. 实现接口方法时使用@Override注解");
System.out.println("3. 重写抽象方法时使用@Override注解");
System.out.println("4. 重写超类具体方法时使用@Override注解");
System.out.println("5. 重写默认方法时也可以使用@Override注解");
System.out.println("\n好处:");
System.out.println("- 编译器检查重写是否正确");
System.out.println("- 提高代码可读性");
System.out.println("- 防止拼写错误或签名错误");
System.out.println("- 便于重构和维护");
}
// 测试
public static void main(String[] args) {
OverrideAnnotationAnalysis demo = new OverrideAnnotationAnalysis();
demo.demonstrateImportance();
}
}
```
## 方法重写的高级主题与最佳实践
深入探讨方法重写的复杂场景和最佳实践。
```java
// 方法重写的高级应用
public class AdvancedOverrideTopics {
// 1. 桥接方法(Bridge Methods) - 泛型擦除导致的特殊情况
class GenericBase<T> {
public T process(T input) {
System.out.println("GenericBase.process: " + input);
return input;
}
}
<"sas.j9k5.org.cn"><"vnd.j9k5.org.cn"><"dsn.j9k5.org.cn">
class StringProcessor extends GenericBase<String> {
@Override
public String process(String input) {
System.out.println("StringProcessor.process: " + input);
return input.toUpperCase();
}
// 编译器会自动生成桥接方法:
// public Object process(Object input) {
// return process((String)input);
// }
}
// 2. 受检异常的重写规则
class BaseWithException {
public void riskyMethod() throws IOException {
System.out.println("Base.riskyMethod");
}
public void anotherMethod() throws Exception {
System.out.println("Base.anotherMethod");
}
}
class DerivedWithException extends BaseWithException {
@Override
public void riskyMethod() throws FileNotFoundException { // 允许抛出更具体的异常
System.out.println("Derived.riskyMethod");
}
@Override
public void anotherMethod() { // 允许不抛出任何异常
System.out.println("Derived.anotherMethod - 没有异常");
}
// 不允许抛出更通用的异常
// @Override
// public void riskyMethod() throws Exception { // 编译错误
// System.out.println("错误的重写");
// }
}
// 3. synchronized方法的重写
class SynchronizedBase {
public synchronized void syncMethod() {
System.out.println("SynchronizedBase.syncMethod - 同步方法");
}
}
class SynchronizedDerived extends SynchronizedBase {
@Override
public void syncMethod() { // 可以不是synchronized
System.out.println("SynchronizedDerived.syncMethod - 非同步方法");
super.syncMethod();
}
}
class AlsoSynchronizedDerived extends SynchronizedBase {
@Override
public synchronized void syncMethod() { // 也可以是synchronized
System.out.println("AlsoSynchronizedDerived.syncMethod - 同步方法");
}
}
// 4. 重写与访问权限的最佳实践
public class AccessControlExample {
// 包私有方法 - 只能被同一个包内的子类重写
void packagePrivateMethod() {
System.out.println("包私有方法");
}
// 受保护方法 - 可以被任何子类重写
protected void protectedMethod() {
System.out.println("受保护方法");
}
// 公有方法
public void publicMethod() {
System.out.println("公有方法");
}
// 私有方法 - 不能被重写
private void privateMethod() {
System.out.println("私有方法");
}
}
// 5. 使用模板方法模式
abstract class DataProcessorTemplate {
// 模板方法 - 定义算法骨架
public final void process() { // final防止子类重写整个流程
loadData();
validateData();
transformData();
saveResults();
cleanup();
}
private void loadData() {
System.out.println("加载数据...");
}
// 钩子方法 - 子类可以重写
protected void validateData() {
System.out.println("默认验证...");
}
// 抽象方法 - 子类必须实现
protected abstract void transformData();
protected void saveResults() {
System.out.println("保存结果到默认位置...");
}
private void cleanup() {
System.out.println("清理资源...");
}
}
class CustomDataProcessor extends DataProcessorTemplate {
@Override
protected void validateData() {
System.out.println("自定义验证逻辑...");
}
@Override
protected void transformData() {
System.out.println("自定义转换逻辑...");
}
@Override
protected void saveResults() {
System.out.println("保存结果到自定义位置...");
}
}
// 6. 重写equals和hashCode的规范
class ProperEntity {
private final String id;
private String name;
private int version;
public ProperEntity(String id, String name) {
this.id = id;
this.name = name;
this.version = 1;
}
@Override
public boolean equals(Object obj) {
// 1. 检查是否为同一对象
if (this == obj) return true;
// 2. 检查是否为null或类型不同
if (obj == null || getClass() != obj.getClass()) return false;
// 3. 类型转换
ProperEntity other = (ProperEntity) obj;
// 4. 比较关键字段
return id.equals(other.id);
}
@Override
public int hashCode() {
// 必须与equals保持一致
return Objects.hash(id);
}
@Override
public String toString() {
return String.format("ProperEntity{id='%s', name='%s', version=%d}",
id, name, version);
}
}
// 7. 处理重写中的组合与继承
class Component {
public void operation() {
System.out.println("Component.operation");
}
}
class Wrapper {
private final Component component;
public Wrapper(Component component) {
this.component = component;
}
// 使用组合而不是继承
public void operation() {
System.out.println("Wrapper.operation - 前置处理");
component.operation();
System.out.println("Wrapper.operation - 后置处理");
}
}
// 演示高级主题
public void demonstrateAdvancedTopics() {
System.out.println("=== 高级重写主题 ===");
System.out.println("\n1. 桥接方法演示:");
GenericBase<String> processor = new StringProcessor();
String result = processor.process("hello");
System.out.println("处理结果: " + result);
System.out.println("\n2. 异常处理规则:");
DerivedWithException derived = new DerivedWithException();
try {
derived.riskyMethod();
derived.anotherMethod();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("\n3. 同步方法重写:");
SynchronizedBase base1 = new SynchronizedDerived();
base1.syncMethod();
SynchronizedBase base2 = new AlsoSynchronizedDerived();
base2.syncMethod();
System.out.println("\n4. 模板方法模式:");
DataProcessorTemplate processorTemplate = new CustomDataProcessor();
processorTemplate.process();
System.out.println("\n5. equals和hashCode重写:");
ProperEntity entity1 = new ProperEntity("001", "实体1");
ProperEntity entity2 = new ProperEntity("001", "实体2");
ProperEntity entity3 = new ProperEntity("002", "实体3");
System.out.println("entity1.equals(entity2): " + entity1.equals(entity2));
System.out.println("entity1.equals(entity3): " + entity1.equals(entity3));
System.out.println("entity1.hashCode == entity2.hashCode: " +
(entity1.hashCode() == entity2.hashCode()));
System.out.println("\n6. 组合优于继承:");
Component component = new Component();
Wrapper wrapper = new Wrapper(component);
wrapper.operation();
System.out.println("\n=== 最佳实践总结 ===");
System.out.println("1. 总是使用@Override注解");
System.out.println("2. 保持重写方法的契约(异常、返回类型、访问权限)");
System.out.println("3. 考虑使用模板方法模式固定算法骨架");
System.out.println("4. 重写equals时必须重写hashCode");
System.out.println("5. 优先使用组合而非继承来扩展功能");
System.out.println("6. 理解桥接方法的生成机制");
System.out.println("7. 注意同步方法的继承语义");
}
// 测试
public static void main(String[] args) {
AdvancedOverrideTopics demo = new AdvancedOverrideTopics();
demo.demonstrateAdvancedTopics();
}
}
```
## 总结
方法重写是Java实现运行时多态的核心机制,通过方法表(vtable)和动态绑定实现。它与方法重载有本质区别:重写基于继承关系,在运行时确定调用;重载基于参数类型,在编译时确定调用。
正确的重写必须遵守严格的规则:方法签名完全相同,访问权限不能更严格,返回类型可以协变,异常声明可以更具体或省略。@Override注解是保证重写正确性的重要工具,能帮助编译器检查错误并提高代码可读性。
理解重写的底层原理——包括JVM的方法表机制、桥接方法生成、性能优化策略等——有助于编写更高效的Java代码。在实际开发中,合理运用重写机制,结合设计模式如模板方法模式,可以构建出灵活、可扩展的软件架构。
遵循最佳实践,如始终使用@Override注解、保持方法契约、正确处理异常和同步语义,能够避免许多常见的编程错误。掌握方法重写的方方面面,是成为高级Java开发者的重要一步。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/19545/viewspace-3110391/ ,如需转载,请注明出处,否则将追究法律责任。