ITPub博客

首页 > 应用开发 > IT综合 > 方法重写深度解析:规则、原理与重载对比

方法重写深度解析:规则、原理与重载对比

翻译 IT综合 作者:bhluo 时间:2026-02-10 15:20:16 0 删除 编辑

# 方法重写深度解析:规则、原理与重载对比


## 方法重写的基本规则与要求


方法重写是面向对象多态性的核心实现机制,必须遵循严格的语法规则。


```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/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2015-11-01

  • 博文量
    895
  • 访问量
    933672