面试题答案
一键面试重写方法的访问修饰符
- 规则:重写方法的访问修饰符不能比被重写方法的访问修饰符更严格。例如,如果父类方法是
protected
,子类重写该方法不能使用private
,可以使用protected
或者public
。这是因为多态要求子类对象能当作父类对象使用,如果重写方法访问修饰符更严格,在使用父类引用调用该方法时可能会导致访问受限问题。 - 示例:
class Parent {
protected void method() {
System.out.println("Parent method");
}
}
class Child extends Parent {
@Override
public void method() {
System.out.println("Child method");
}
}
重写方法的参数列表
- 规则:重写方法的参数列表必须与被重写方法的参数列表完全相同,包括参数的数量、类型和顺序。这是因为Java通过方法签名(方法名 + 参数列表)来区分不同的方法,只有参数列表相同才能确保是对父类方法的重写,而不是定义了一个新的方法。
- 示例:
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);
}
}
重写方法的异常抛出规则
- 规则:
- 重写方法不能抛出比被重写方法更多的受检异常(checked exception)。例如,父类方法抛出
IOException
,子类重写方法不能抛出IOException
和SQLException
,只能抛出IOException
或者其子类异常,或者不抛出异常。 - 重写方法可以抛出更少的受检异常,甚至不抛出受检异常。
- 对于非受检异常(unchecked exception,如
RuntimeException
及其子类),没有限制,重写方法可以抛出与父类相同、更多或更少的非受检异常。
- 重写方法不能抛出比被重写方法更多的受检异常(checked exception)。例如,父类方法抛出
- 示例:
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
}
}
实际项目开发中适合利用继承与方法重写实现多态优化代码结构的场景及思路
- 场景:图形绘制系统。假设有一个图形绘制的项目,需要绘制不同的图形,如圆形、矩形、三角形等。
- 实现思路:
- 首先定义一个父类
Shape
,包含一个抽象方法draw
。
- 首先定义一个父类
abstract class Shape {
abstract void draw();
}
- 然后分别定义
Circle
、Rectangle
、Triangle
等子类继承自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
方法即可,而不需要修改主程序中图形绘制的核心逻辑,提高了代码的可维护性和可扩展性。