从零开始的Java学习(8)

Episode-8 Java运行时多态的简单使用

当谈论Java中的面向对象编程时,一个重要的概念就是多态性(Polymorphism)。Java多态性是指对象可以有多种形态。在Java中,多态性有两种形式,一种是编译时多态性,另一种是运行时多态性。Java中的编译时多态主要体现在方法的重载(overload)上,相信大家已经对此十分了解,故在此文章中不再赘述。

让我们一起探究Java的运行时多态吧!
(下面的多态均为运行时多态)

本期学习相关的知识

  • 使用抽象类的多态
  • 使用接口的多态
  • 使用泛型的多态

使用抽象类的多态

多态有两个条件,一是继承,二是重写(override)。

假设我们需要处理多种动物,每种动物都需要吃东西,但是每种动物吃饭的具体特性都不相同,为了简化处理过程,我们需要使用多态。

让我们先定义一个抽象的父类"Animal":

public abstract class Animal {
    public abstract void eat();
}

再写几个子类来继承并重写eat()方法:

子类:“猫”:

public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("Cat is eating fish");
    }
}

子类:“狗”:

public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("Dog is eating meat");
    }
}

现在,我们可以再写一个程序来测试上面的代码:

public class Main {
    public static void main(String[] args) {
        Animal animal1 = new Cat();
        Animal animal2 = new Dog();

        animal1.eat(); // 输出 "Cat is eating fish"
        animal2.eat(); // 输出 "Dog is eating meat"
    }
}

下面是在上述示例在命令行中运行的结果:

abstract

虽然每种动物的eat()方法都不尽相同,但在Main.java中,我们对它们使用了相同的Animal调用,却正确地输出了具体动物的特定eat()方法里的内容。

使用接口的多态

接口是一个重要的概念,在这篇文章中我们暂且讨论它在简单的多态中的使用。

假如我们需要对不同的形状进行处理,那么我们根据之前的经验,应该先定义一个接口,各种具体的形状应该各自实现这个接口。

下面是接口"Shape"的一个示例:

public interface Shape {
    public void draw();
}

接下来,我们定义两个形状————圆形"Circle"和方形"Square"。

Circle.java的内容:

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

Square.java的内容:

public class Square implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a square");
    }
}

同样的,让我们写一个测试程序Main.java:

public class Main {
    public static void main(String[] args) {
        Shape shape1 = new Circle();
        Shape shape2 = new Square();

        shape1.draw(); // 输出 "Drawing a circle"
        shape2.draw(); // 输出 "Drawing a square"
    }
}

上述程序在命令行中的运行结果如下:

interface

上面只是一个简单的示例,以后我们会分析更加复杂的程序。

使用泛型的多态

泛型的用法比较多,具体可以参见:泛型-菜鸟教程

实际上,泛型也是Java多态性的体现。

以"T"为例,在泛型实际引用的类型不同时,会根据具体的类型进行对应的处理。

现在我们可以定义一个泛型类"Box"来切身体会这一点:

public class Box<T> {
    private T content;

    public void add(T content) {
        this.content = content;
    }

    public T getContent() {
        return content;
    }
}

上面的代码定义了一个泛型类,它被定义为Box<T>,其中T是一个泛型类型参数,可以被任何Java类或接口代替。这个类表示一个简单的容器,可以存储一个类型为T的对象。

这个类有两个方法:add()getContent()add()方法接受一个类型为T的对象作为参数,并将它存储在Box类的私有成员变量content中。getContent()方法返回存储在content中的对象,这个对象的类型也是T。

使用泛型类的好处是可以在编译时进行类型检查,从而避免在运行时出现类型错误。这个类可以用来存储各种不同类型的对象,只需要在创建实例时指定相应的类型即可。例如:

public class Main {
    public static void main(String[] args) {
        Box<Integer> intBox = new Box<Integer>();
        intBox.add(123);

        Box<String> strBox = new Box<String>();
        strBox.add("Hello, world!");

        System.out.println(intBox.getContent()); // 输出 123
        System.out.println(strBox.getContent()); // 输出 "Hello, world!"
    }
}

按照惯例,让我们看看它在命令行中的运行结果:

generics

虽然使用泛型的多态与前面两个示例有些微的不同,但它们的核心是:对各种不同的对象进行统一地处理,输出不同的结果。

希望本篇文章会对你的学习有所帮助。

谢谢观看!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值