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 注解,确保方法覆盖的正确性。

相关推荐
77qqqiqi16 分钟前
正则表达式
java·后端·正则表达式
慧一居士34 分钟前
<script setup>中的setup作用以及和不带的区别对比
前端
@大迁世界1 小时前
AR 如何改变我们构建网站的方式
后端·ar·restful
RainbowSea1 小时前
NVM 切换 Node 版本工具的超详细安装说明
java·前端
读书点滴1 小时前
笨方法学python -练习14
java·前端·python
RainbowSea1 小时前
问题:后端由于字符内容过长,前端展示精度丢失修复
java·spring boot·后端
Mintopia1 小时前
四叉树:二维空间的 “智能分区管理员”
前端·javascript·计算机图形学
Mintopia1 小时前
Three.js 深度冲突:当像素在 Z 轴上玩起 "挤地铁" 游戏
前端·javascript·three.js
风象南1 小时前
SpringBoot 控制器的动态注册与卸载
java·spring boot·后端
Penk是个码农1 小时前
web前端面试-- MVC、MVP、MVVM 架构模式对比
前端·面试·mvc