Java 多态
什么是多态
Java 的多态是面向对象编程的重要特性,它允许同一个类的不同对象实例对同一个方法做出不同的响应。简单说,多态就是同一种类型的对象,在不同的情况下会表现出不同的行为。
现实中也有很多例子:
- 在线聊天可以用 QQ,可以用微信,但是都是在线聊天。
- 绿色出行可以坐公交,可以坐地铁,但是都是出行。
多态的实现方式
在 Java 中,多态可以由继承和接口两种机制实现,通过实现、重写、指定的方法,Java 可以让程序在运行时动态地选择调用哪个方法,从而实现多态。这种特性可以使代码更加灵活,减少代码冗余,提高代码的可读性和可维护性。
继承实现多态
public class Animal{
public void makeSound(){
System.out.println("动物发出叫声");
}
}
// 然后我们有一个猫类Cat,它继承了Animal类,但是它的叫声不同:
public class Cat extends Animal{
@Override
public void makeSound(){
System.out.println("喵喵喵");
}
}
// 同样,我们有一个狗类Dog,它也继承了Animal类,但是它的叫声不同:
public class Dog extends Animal{
@Override
public void makeSound(){
System.out.println("汪汪汪");
}
}
现在我们可以创建两个 Animal 对象,分别是猫和狗的实例。它们同样的方法,但是表现出的行为不同。
Animal cat = new Cat();
Animal dog = new Dog();
for (Animal animal : Arrays.asList(cat, dog)) {
animal.makeSound();
}
// 喵喵喵
// 汪汪汪
这是一种 Java 多态的实现方式,不同的子类继承了同一个父类,重写了同一个方法,表现出的行为不同。这样的设计,使得代码更加灵活,具有更好的可扩展性和可维护性。
接口实现多态
实现接口和继承类实现多态大致相同。
public interface Animal{
void makeSound();
}
// 然后我们有一个猫类Cat,和一个狗类Dog,Animal,并且都有自己特定的叫声:
public class Cat implements Animal{
@Override
public void makeSound(){
System.out.println("喵喵喵");
}
}
public class Dog implements Animal{
@Override
public void makeSound(){
System.out.println("汪汪汪");
}
}
同样的测试:
Animal cat = new Cat();
Animal dog = new Dog();
for (Animal animal : Arrays.asList(cat, dog)) {
animal.makeSound();
}
// 喵喵喵
// 汪汪汪
多态的特点
多态的一大特点就是运行时才决定调用的是哪个方法,上面的例子中,都是对一个 Animal
对象调用,然后表现出来的行为不同。完全可以以 Animal
类型作为方法的入参,这样这个方法就不用关心传入的是 Cat
还是 Dog
,调用 makeSound
方法的行为会在运行时动态决定。
/**
* @author www.wdbyte.com
* @date 2023/04/18
*/
public class Test2 {
public static void main(String[] args) {
Animal cat = new Cat();
Animal dog = new Dog();
makeSound(cat); // 喵喵喵
makeSound(dog); // 汪汪汪
}
public static void makeSound(Animal animal) {
animal.makeSound();
}
}
多态的优点
Java中的多态优点如下:
- 提高代码的可扩展性和可维护性:多态可以让程序员在不修改已有代码的情况下扩展系统的功能,从而降低了系统的维护成本。
- 简化代码的逻辑:多态可以让程序员只需要关注对象的行为,而不必关心具体的对象类型。
- 提高代码的重用性:通过继承和接口的方式,可以将代码的相同部分抽取出来,减少了代码冗余,提高了代码的重用性。
- 提高代码的灵活性:多态可以让程序员在运行时动态地选择具体的实现方式,从而提高了代码的灵活性和可配置性。
- 提高代码的可读性和可理解性:多态可以让代码更加直观和易于理解,提高了代码的可读性和可理解性。
为什么要用多态
上面的例子已经举例了多态的用法,多态的优点也就是使用多态的原因。下面再举一个例子进行说明。
假如你要开发一个功能,允许用户可以向阿里云 OSS 或者腾讯云 OSS 上传文件内容。不使用多态,你可能需要编写两个独立的阿里云 OSS 操作类,腾讯云 OSS 操作类,那么使用多态如何实现呢?
- 定义一个 Oss 操作接口。
/**
* @author www.wdbyte.com
*/
public interface Oss {
/**
* 文件上传
* @param content
*/
void upload(String content);
}
-
定义阿里云 OSS 和腾讯云 OSS 类。
public class AliyunOss implements Oss { @Override public void upload(String content) { try { Thread.sleep(10); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("文件已经上传到阿里云 OSS,内容:" + content); } } public class TencentOss implements Oss { @Override public void upload(String content) { try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("文件已经上传到腾讯云 OSS,内容:" + content); } }
-
定义 Oss 操作工具类,可以统计上传耗时。
public class OssUtil { /** * OSS 上传工具类 * * @param oss * @param content */ public static void upload(Oss oss, String content) { long start = System.currentTimeMillis(); oss.upload(content); long end = System.currentTimeMillis(); System.out.println("上传耗时:" + (end - start) + "ms"); } }
-
测试阿里云 OSS 和腾讯云 OSS 内容上传。
public static void main(String[] args) { AliyunOss aliyunOss = new AliyunOss(); TencentOss tencentOss = new TencentOss(); upload(aliyunOss, "Hello aliyun"); System.out.println("------------"); upload(tencentOss, "Hello tencent"); } // 文件已经上传到阿里云 OSS,内容:Hello aliyun // 上传耗时:12ms // ------------ // 文件已经上传到腾讯云 OSS,内容:Hello tencent // 上传耗时:101ms
这里的 OssUtil
是完全独立的,入参的类型是 Oss
,不管以后增加了华为云 Oss 还是谷歌云 Oss,都只需要定义相应的 Oss 类即可,提高了代码的可扩展性,可复用性。
一如既往,文章中代码存放在 Github.com/niumoo/javaNotes.