Java 中的向上转型和向下转型
1、简介
了解如何处理 Java 类型层次结构中的对象对于编写灵活和可维护的代码至关重要。在这个领域中,两个基本概念是向上转型(Upcasting)和向下转型(Downcasting)。
本文将带你深入了解这些概念,探索它们之间的区别,以及它们在 Java 中的原理。
2、Java 中的类型转换
Java 是一种面向对象的编程语言(Object Oriented Programming,OOP),允许在其类型系统中将一种类型转换为另一种类型。转换是将一种类类型的引用转换为另一种类类型的过程。具体来说,Java 中主要有两种类型的转换:向上转型(Upcasting)和向下转型(Downcasting)。
假设我们有一个类的层次结构,其中 Dog
是 Animal
的子类。下图显示了向上转型(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");
}
}
如上,定义了两个类:Animal
和 Dog
。Animal
类有一个 makeSound()
方法,用于打印 “Animal sound(动物的声音)”,Dog
类继承了 Animal
,它覆写了 makeSound()
方法,打印 “Bark(狗叫)”,并引入了一个新方法 fetch()
,用于打印 “Dog fetches”。
Animal myDog = new Dog();
myDog.makeSound();
如上例,创建了一个 Dog
类的实例,并将其赋值给一个 Animal
类型的变量。当我们调用 myDog
的 makeSound()
方法时,它会调用 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