Java编译时多态和运行时多态

在面向对象编程中,多态是一个重要的概念。它允许我们以统一的方式处理不同类型的对象,并在运行时根据对象的实际类型调用相应的方法。在Java中,多态有两种形式:编译时多态和运行时多态。本文将详细介绍这两种多态形式的概念以及如何使用它们。

编译时多态

在编译时多态中,方法的调用是在编译时确定的,即根据引用变量的类型来决定调用哪个方法。这种多态是通过方法重载实现的。方法重载是指在同一个类中定义多个同名的方法,但它们的参数列表不同。编译器根据参数的数量和类型来选择调用哪个方法。

让我们看一个简单的例子来理解编译时多态:

public class PolymorphismExample {
    public static void main(String[] args) {
        Shape shape = new Shape();
        shape.draw();

        Circle circle = new Circle();
        circle.draw();

        Rectangle rectangle = new Rectangle();
        rectangle.draw();
    }
}

class Shape {
    public void draw() {
        System.out.println("Drawing a shape");
    }
}

class Circle extends Shape {
    public void draw() {
        System.out.println("Drawing a circle");
    }
}

class Rectangle extends Shape {
    public void draw() {
        System.out.println("Drawing a rectangle");
    }
}

在上面的代码中,我们定义了一个Shape类和两个子类CircleRectangleShape类有一个draw方法,CircleRectangle类分别重写了draw方法。

main方法中,我们创建了一个Shape对象,并调用了它的draw方法。由于shape变量的类型是Shape,编译器会在编译时确定调用Shape类的draw方法。

接下来,我们创建了一个Circle对象,并调用了它的draw方法。同样,由于circle变量的类型是Circle,编译器会在编译时确定调用Circle类的draw方法。

最后,我们创建了一个Rectangle对象,并调用了它的draw方法。同样,由于rectangle变量的类型是Rectangle,编译器会在编译时确定调用Rectangle类的draw方法。

在以上所有情况中,编译器根据变量的类型来确定调用哪个方法。这就是编译时多态。

运行时多态

在运行时多态中,方法的调用是在运行时确定的,即根据对象的实际类型来决定调用哪个方法。这种多态是通过方法重写实现的。方法重写是指在子类中定义一个与父类中具有相同名称和参数列表的方法。当子类对象调用这个方法时,将执行子类中的方法而不是父类中的方法。

让我们看一个简单的例子来理解运行时多态:

public class PolymorphismExample {
    public static void main(String[] args) {
        Shape shape = new Circle();
        shape.draw();

        shape = new Rectangle();
        shape.draw();
    }
}

class Shape {
    public void draw() {
        System.out.println("Drawing a shape");
    }
}

class Circle extends Shape {
    public void draw() {
        System.out.println("Drawing a circle");
    }
}

class Rectangle extends Shape {
    public void draw() {
        System.out.println("Drawing a rectangle");
    }
}

在上面的代码中,我们创建了一个Shape对象,并将它赋值给一个shape变量。然后,我们调用了shapedraw方法。由于shape变量的实际类型是Circle,所以运行时会调用Circle类的draw方法。

接下来,我们将一个Rectangle对象赋值给shape变量,并再次调用了shapedraw方法。由于shape变量的实际类型是Rectangle,所以运行时会调用Rectangle类的draw方法。

在以上所有情况中,方法的调用是在运行时确定的,根据对象的实