Java 中的向上转型和向下转型

1、简介

了解如何处理 Java 类型层次结构中的对象对于编写灵活和可维护的代码至关重要。在这个领域中,两个基本概念是向上转型(Upcasting)和向下转型(Downcasting)。

本文将带你深入了解这些概念,探索它们之间的区别,以及它们在 Java 中的原理。

2、Java 中的类型转换

Java 是一种面向对象的编程语言(Object Oriented Programming,OOP),允许在其类型系统中将一种类型转换为另一种类型。转换是将一种类类型的引用转换为另一种类类型的过程。具体来说,Java 中主要有两种类型的转换:向上转型(Upcasting)和向下转型(Downcasting)。

假设我们有一个类的层次结构,其中 DogAnimal 的子类。下图显示了向上转型(Upcasting)和向下转型(Downcasting)在这个层次结构中的工作原理:

ava 类型系统中的向上转型(Upcasting)和向下转型(Downcasting)

向上转型(Upcasting)箭头从 Dog 类移动到 Animal 类,显示了子类引用(Dog)如何泛化为父类引用(Animal)。而,向下转型(Downcasting)箭头从 Animal 类返回 Dog 类,显示父类引用(Animal)如何再次被指定为子类引用(Dog)。

但是,如果尝试使用 Animal 引用实例化 Dog 对象,则会因类型不兼容而导致编译错误。

Dog dog = new Animal(); //异常 ClassCastException

3、Java 向上转型

向上转型(Upcasting)是指将子类引用转换为父类引用。这种类型的转换是隐式的,在处理多态性时经常使用它。

向上转型(Upcasting)允许我们将一个子类的对象当作一个父类的对象来处理:

class Animal {
    public void makeSound() {
        System.out.println("Animal sound");
    }
}

class Dog extends Animal {
    public void makeSound() {
        System.out.println("Bark");
    }

    public void fetch() {
        System.out.println("Dog fetches");
    }
}

如上,定义了两个类:AnimalDogAnimal 类有一个 makeSound() 方法,用于打印 “Animal sound(动物的声音)”,Dog 类继承了 Animal,它覆写了 makeSound() 方法,打印 “Bark(狗叫)”,并引入了一个新方法 fetch(),用于打印 “Dog fetches”。

Animal myDog = new Dog();
myDog.makeSound();

如上例,创建了一个 Dog 类的实例,并将其赋值给一个 Animal 类型的变量。当我们调用 myDogmakeSound() 方法时,它会调用 Dog 类中的重载方法,在控制台中打印 “Bark”。

4、Java 向下转型

相反,向下转型(Downcasting)则是将父类引用转换回子类引用。与向上转型不同,向下转型是显式的,需要小心处理。因此,必须确保被传递的对象与目标类型相匹配,以避免发生 ClassCastException

当需要访问父类中没有的子类的特定方法或字段时,就会使用向下转型(强制转型):

Animal myAnimal = new Dog();
// 强制把 Animal 类型的 myAnimal 对象转换为 Dog 对象
Dog myDog2 = (Dog) myAnimal;
myDog2.makeSound();
myDog2.fetch();

如上,首先将 Dog 对象向上转型为 Animal 引用。然后,将它强制转换(向下转型)为 Dog 引用。这种方式允许我们同时调用 makeSound() 方法(从 Animal 类继承)和 fetch() 方法(Dog 类特有)。

通过向下转型,可以重新访问子类的方法和字段。

5、向上转型和向下转型

向上转型和向下转型的主要区别和特点如下表:

特点 向上转型 向下转型
定义 将子类引用转换为父类引用 将父类引用转换为子类引用
隐式或显式 隐式 显式
常见用法 在多态中使用,用于将对象泛化 用于访问特定子类的功能
类型安全 安全,无需类型检查 需要类型检查以避免 ClassCastException
对子类方法的访问 只能访问父类方法 允许访问子类特有的方法和字段
示例场景 Dog 对象传递给参数为 Animal 对象的方法 Animal 引用强制转换为 Dog,以调用 Dog 的特定方法
性能 由于没有运行时的类型检查,一般来说效率更高 由于运行时类型检查,效率略低

6、总结

向上转型(Upcasting)和向下转型(Downcasting)都是 Java 类型系统不可或缺的一部分,它们通过继承和多态促进了代码的灵活性和可重用性。


Ref:https://www.baeldung.com/java-upcasting-vs-downcasting