MST

星途 面试题库

面试题:Java多态中继承与方法重写的细节与应用场景

在Java中,当一个子类继承父类并重写父类方法实现多态时,谈谈你对重写方法的访问修饰符、参数列表以及异常抛出规则的理解。同时,举例说明在实际项目开发中,哪些场景适合利用这种继承与方法重写实现的多态来优化代码结构,并阐述具体的实现思路。
25.6万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

重写方法的访问修饰符

  1. 规则:重写方法的访问修饰符不能比被重写方法的访问修饰符更严格。例如,如果父类方法是 protected,子类重写该方法不能使用 private,可以使用 protected 或者 public。这是因为多态要求子类对象能当作父类对象使用,如果重写方法访问修饰符更严格,在使用父类引用调用该方法时可能会导致访问受限问题。
  2. 示例
class Parent {
    protected void method() {
        System.out.println("Parent method");
    }
}
class Child extends Parent {
    @Override
    public void method() {
        System.out.println("Child method");
    }
}

重写方法的参数列表

  1. 规则:重写方法的参数列表必须与被重写方法的参数列表完全相同,包括参数的数量、类型和顺序。这是因为Java通过方法签名(方法名 + 参数列表)来区分不同的方法,只有参数列表相同才能确保是对父类方法的重写,而不是定义了一个新的方法。
  2. 示例
class Parent {
    void method(int num) {
        System.out.println("Parent method with int param: " + num);
    }
}
class Child extends Parent {
    @Override
    void method(int num) {
        System.out.println("Child method with int param: " + num);
    }
}

重写方法的异常抛出规则

  1. 规则
    • 重写方法不能抛出比被重写方法更多的受检异常(checked exception)。例如,父类方法抛出 IOException,子类重写方法不能抛出 IOExceptionSQLException,只能抛出 IOException 或者其子类异常,或者不抛出异常。
    • 重写方法可以抛出更少的受检异常,甚至不抛出受检异常。
    • 对于非受检异常(unchecked exception,如 RuntimeException 及其子类),没有限制,重写方法可以抛出与父类相同、更多或更少的非受检异常。
  2. 示例
class Parent {
    void method() throws IOException {
        // some code that may throw IOException
    }
}
class Child extends Parent {
    @Override
    void method() throws FileNotFoundException {
        // some code that may throw FileNotFoundException which is a subclass of IOException
    }
}

实际项目开发中适合利用继承与方法重写实现多态优化代码结构的场景及思路

  1. 场景:图形绘制系统。假设有一个图形绘制的项目,需要绘制不同的图形,如圆形、矩形、三角形等。
  2. 实现思路
    • 首先定义一个父类 Shape,包含一个抽象方法 draw
abstract class Shape {
    abstract void draw();
}
  • 然后分别定义 CircleRectangleTriangle 等子类继承自 Shape 类,并实现 draw 方法。
class Circle extends Shape {
    @Override
    void draw() {
        System.out.println("Drawing a circle");
    }
}
class Rectangle extends Shape {
    @Override
    void draw() {
        System.out.println("Drawing a rectangle");
    }
}
class Triangle extends Shape {
    @Override
    void draw() {
        System.out.println("Drawing a triangle");
    }
}
  • 在主程序中,可以使用一个 Shape 类型的数组来存储不同的图形对象,并通过遍历数组调用 draw 方法,实现多态。
public class Main {
    public static void main(String[] args) {
        Shape[] shapes = new Shape[]{new Circle(), new Rectangle(), new Triangle()};
        for (Shape shape : shapes) {
            shape.draw();
        }
    }
}

这样的代码结构使得添加新的图形变得非常容易,只需要创建一个新的继承自 Shape 的子类并实现 draw 方法即可,而不需要修改主程序中图形绘制的核心逻辑,提高了代码的可维护性和可扩展性。