- 子类重写
calculateArea
方法的要求
- 方法签名必须一致:在
Circle
和Rectangle
子类中,calculateArea
方法的返回类型、方法名和参数列表必须与Shape
抽象类中的抽象方法calculateArea
完全一致。因为Shape
类中calculateArea
是抽象方法,没有方法体,所以在Circle
和Rectangle
子类中必须提供具体的实现。
- 访问修饰符不能更严格:
Circle
和Rectangle
子类中calculateArea
方法的访问修饰符不能比Shape
类中抽象方法的访问修饰符更严格。例如,如果Shape
类中calculateArea
方法是protected
,那么在子类中可以是protected
或public
,但不能是private
。
- 利用多态性在主程序中实现获取面积值
abstract class Shape {
public abstract double calculateArea();
}
class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}
class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double calculateArea() {
return width * height;
}
}
public class Main {
public static void main(String[] args) {
Shape circle = new Circle(5);
Shape rectangle = new Rectangle(4, 6);
System.out.println("Circle area: " + circle.calculateArea());
System.out.println("Rectangle area: " + rectangle.calculateArea());
}
}
- 解释:在主程序中,定义了
Shape
类型的变量circle
和rectangle
,但分别指向Circle
和Rectangle
的实例。这就是多态性的体现,即相同的方法调用(calculateArea
),根据对象的实际类型(Circle
或Rectangle
),调用相应子类的calculateArea
方法,从而获取正确的面积值。
- 涉及到的Java虚拟机机制
- 动态绑定:在运行时,Java虚拟机根据对象的实际类型来确定调用哪个方法。在上述例子中,当调用
circle.calculateArea()
时,Java虚拟机知道circle
实际指向的是Circle
对象,所以调用Circle
类中的calculateArea
方法;当调用rectangle.calculateArea()
时,因为rectangle
实际指向Rectangle
对象,所以调用Rectangle
类中的calculateArea
方法。这种动态绑定机制使得Java能够实现多态性。
- 方法表:Java虚拟机为每个类维护一个方法表,方法表中记录了类及其父类中所有可被调用的方法的实际地址。当对象调用方法时,Java虚拟机通过对象的实际类型找到对应的方法表,然后根据方法表中记录的地址调用具体的方法。例如,
Circle
对象调用calculateArea
方法时,Java虚拟机在Circle
类的方法表中找到calculateArea
方法的实际地址并执行该方法。