104. Java 继承 - 实例方法的覆盖

104. Java 继承 - 实例方法的覆盖

在 Java 中,子类可以覆盖(重写)从父类继承来的实例方法。覆盖意味着子类提供了一个新的实现来替代父类中继承的方法。为了使方法覆盖有效,子类中的方法必须与父类中的方法具有相同的签名:方法名称、参数的数量和类型以及返回类型。

方法覆盖

当子类中存在与父类相同签名的实例方法时,子类的方法会覆盖父类中的方法。这个能力允许子类从父类继承足够接近的行为,然后根据需要修改这些行为。

例如:

java 复制代码
class Animal {
    public void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Dog barks");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        myDog.sound(); // 输出:Dog barks
    }
}

在上面的例子中,Dog 类覆盖了 Animal 类中的 sound() 方法。即使 myDog 变量被声明为 Animal 类型,实际调用的是 Dog 类中重写后的 sound() 方法。这是因为 Dog 类重写了父类 Animal 中的 sound() 方法。

协变返回类型(Covariant Return Types)

当子类覆盖父类方法时,子类可以改变方法的返回类型,只要返回类型是父类方法返回类型的子类型。这样的返回类型被称为 协变返回类型(Covariant Return Type)。

例如:

java 复制代码
class Animal {
    public Animal getAnimal() {
        return new Animal();
    }
}

class Dog extends Animal {
    @Override
    public Dog getAnimal() {
        return new Dog();
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Animal();
        Dog myDog = new Dog();
        
        Animal a = myAnimal.getAnimal(); // 返回类型是 Animal
        Dog d = myDog.getAnimal(); // 返回类型是 Dog
    }
}

在上面的代码中,Animal 类的 getAnimal() 方法返回 Animal 类型,而 Dog 类覆盖了该方法,并返回 Dog 类型,这就是协变返回类型的应用。Java 允许子类方法返回比父类方法更加具体的类型。

使用 @Override 注解

虽然 Java 支持方法覆盖,但为了确保程序员的意图明确且避免错误,推荐使用 @Override 注解。@Override 注解告诉编译器我们打算覆盖父类中的方法。如果子类中的方法签名不正确(例如,方法名不匹配或参数数量和类型不一致),编译器将抛出错误。使用 @Override 注解可以帮助我们在编译时发现这些错误,从而避免不必要的运行时错误。

java 复制代码
class Animal {
    public void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Dog barks");
    }
}

在这个示例中,@Override 注解确保了我们确实覆盖了 Animal 类中的 sound() 方法。如果我们在 Dog 类中错误地拼写方法名或改变方法签名,编译器将会提示错误。

常见错误

如果您尝试覆盖父类中不存在的方法,编译器会在使用 @Override 注解时给出错误。例如:

java 复制代码
class Animal {
    public void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    public void bark() { // 编译错误,因为没有 "bark" 方法
        System.out.println("Dog barks");
    }
}

在这个例子中,Dog 类尝试用 @Override 注解覆盖 bark() 方法,但 Animal 类并没有定义 bark() 方法。因此,编译器会提示错误:"无法找到符号"。

总结
  1. 方法覆盖:子类可以覆盖父类中的实例方法,覆盖方法必须与父类方法的签名(方法名、参数数量和类型、返回类型)一致。
  2. 协变返回类型:子类在覆盖父类方法时,返回类型可以是父类返回类型的子类类型。
  3. @Override 注解@Override 注解用于标记方法覆盖,确保方法签名与父类方法一致。如果不一致,编译器将报错,避免潜在的运行时错误。
  4. 覆盖时的常见错误 :如果子类方法不符合父类方法签名,编译器会报错。通过使用 @Override 注解可以及时捕获这种错误。

通过这些例子和解释,您可以更好地理解 Java 中的实例方法覆盖,以及如何正确使用 @Override 注解,确保方法覆盖的正确性。

相关推荐
javachen__1 分钟前
SpringBoot整合P6Spy实现全链路SQL监控
spring boot·后端·sql
阿珊和她的猫2 小时前
v-scale-scree: 根据屏幕尺寸缩放内容
开发语言·前端·javascript
uzong5 小时前
技术故障复盘模版
后端
GetcharZp6 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
加班是不可能的,除非双倍日工资6 小时前
css预编译器实现星空背景图
前端·css·vue3
桦说编程6 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研6 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi7 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip7 小时前
vite和webpack打包结构控制
前端·javascript
excel7 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端