Java上溯造型(upcasting)与下溯造型(Downcasting)
上溯造型(upcasting)
这个术语缘于继承关系图的传统画法:将基类至于顶部,而向下发展的就是派生类。
文章使用的完整代码如下
public class Main {
public static void main(String[] args) {
Dog dog=new Dog();
upcasting(dog);//汪汪汪。。。
dog.tail();//摇尾巴...
dog.speak();//汪汪汪。。。
Animal animal=new Dog();
animal.speak();//汪汪汪。。。
// animal.tail();//The method tail() is undefined for the type Animal
//下溯
Dog d =(Dog)animal;
d.tail();
//错误的下溯
// Animal a2=new Animal();
// Dog d2=(Dog)a2;
// d2.tail();
// 运行时报错:Exception in thread "main" java.lang.ClassCastException: class shangsu.Animal cannot be cast to class shangsu.Dog (shangsu.Animal and shangsu.Dog are in unnamed module of loader 'app')
// at shangsu.Main.main(Main.java:16)
}
public static void upcasting(Animal animal){
animal.speak();
// animal.tail();//编译错误:The method tail() is undefined for the type Animal
return;
}
}
class Animal {
public void speak(){
// System.out.println("阿巴阿巴。。。");
}
}
class Dog extends Animal{
@Override
public void speak() {
System.out.println("汪汪汪。。。");
}
public void tail(){
System.out.println("摇尾巴...");
}
}
由于upcasting(Animal animal)
方法的参数是 Animal类型的,因此如果传入的参数是Animal的子类,传入的参数就会被转换成父类Animal类型,这样你创建的 Dog对象 能使用的方法只是Animal中的签名方法;也就是说,在上溯的过程中,Dog的接口变窄了,它本身的一些方法(例如tail方法)就不可见了。
如果你 想使用Dog中存在而Animal中不存在的方法 (比如tail方法),编译时不能通过。由此可见,上溯造型是安全的类型转换。另一方面,虽然upcasting(Animal animal)方法的参数是 Animal类型,但传入的参数可以是 Animal的派生类 (这也是OO编程中惯用的编程方法),这里面就有个对象的类型识别问题,也就是运行时类型识别(run-time type identification,缩写为RTTI) 。RTTI的功能主要是由Class类实现的。
简单来说,上溯造型就是把子类向上转换为父类类型Animal animal=new Dog();
,这样转型后只能使用父类中已经声明过的方法(叫)而不能通过转换后的父类调用子类特有的方法(摇尾巴)
下溯造型(Downcasting)
不一定安全,在编译时检测不到,运行时会抛出ClassCastException异常,对于测试来说,这样的错误也是很难检测的。
- 将父类对象显示的转换成子类类型。
- 曾经向上转换过的对象,才能再向下转换。对象不允许不经过上溯造型而直接下溯造型。
Animal animal=new Dog();
Dog d =(Dog)animal;
d.tail();
不正确的下溯示例:
Animal a2=new Animal();//动物类对象a2
Dog d2=(Dog)a2;//下溯为Dog类对象
d2.tail();
//编译时无错误
运行时报错Exception in thread "main" java.lang.ClassCastException: class shangsu.Animal cannot be cast to class shangsu.Dog (shangsu.Animal and shangsu.Dog are in unnamed module of loader 'app') at shangsu.Main.main(Main.java:16)
正确示例:
public static void downcasting(Animal animal){
if(animal instanceof Dog){
Dog dog=(Dog)animal;
dog.speak();
dog.tail();
}
}
Java类中重写equals()
用到的下溯造型
(2021.9.15更新)
Q:为什么要重写equals() ?
A:引用类型比较,要使用
equals()
方法,如果使用==
比较,它比较的是两个引用类型的变量是否是同一个对象。同时,调用List的
contains()
indexOf()
方法 都需要实现equals()
方法
对于自己创造的一个类,本身并没有重写equals()
方法,如果需要比较两个类实例是否相等 就必须要重写(调用List的contains()
indexOf()
方法 也需要重写)
在廖雪峰老师的JAVA教程的一个练习中就有重写equals()的练习,在编写时,我发现这个就是下溯造型,于是在这里写出。
class Person {
String firstName;
String lastName;
int age;
public Person(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
/** * TODO: 覆写equals方法 */
@Override
public boolean equals(Object o) {
if(this == o) {
return true;
}
if(o instanceof Person) {
Person pp=(Person)o;
if(this.firstName.equals(pp.firstName) && this.lastName.equals(pp.lastName) &&this.age==pp.age) {
return true;
}
}
return false;
}
重写后即可完成main函数中的测试
public class Main {
public static void main(String[] args) {
List<Person> list = List.of(new Person("Xiao", "Ming", 18), new Person("Xiao", "Hong", 25),
new Person("Bob", "Smith", 20));
boolean exist = list.contains(new Person("Bob", "Smith", 20));
System.out.println(exist ? "测试成功!" : "测试失败!");
}
}
今天的文章什么是上溯造型_Javajre下载[通俗易懂]分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/86655.html