[Java初学]Java上溯造型(upcasting)与下溯造型(Downcasting)
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 Animalreturn;} }class Animal {public void speak(){// System.out.println("阿巴阿巴。。。");}
}class Dog extends Animal{@Overridepublic 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 ? "测试成功!" : "测试失败!");}
}
[Java初学]Java上溯造型(upcasting)与下溯造型(Downcasting)相关推荐
- 上溯造型、下溯造型的理解
(上溯造型定义:java允许把一个子类对象直接复制给一个父类引用变量,自动完成类型转换,这种语法现象称为上溯造型. 下溯造型回到它自己所在的类(强制转换):一个对象被溯型为父类或接口后还可以再被下溯造 ...
- Java——上溯造型下溯造型
public abstract class Animal {public abstract void speak();public void eat(){// 吃吃吃!!! } } public in ...
- Java 的上溯造型和下溯造型以及举例,以及判断参数等指向的类
(一) 先给出个例子,代码如下: /** * @author WangQun * 动物抽象类 */ abstract class Animal { public abstract void speak ...
- java 下溯造型_Java——上溯造型下溯造型
public abstract class Animal { public abstract void speak(); public void eat(){ // 吃吃吃!!! } } public ...
- java 下溯造型_Java 的上溯造型和下溯造型以及举例,以及判断参数等指向的类
(一) 先给出个例子,代码如下: /** * @author WangQun * 动物抽象类 */ abstract class Animal { public abstract void speak ...
- java上溯造型与下溯造型
Java的多态性 面向对象编程有三个特征,即封装.继承和多态. 封装隐藏了类的内部实现机制,从而可以在不影响使用者的前提下改变类的内部结构,同时保护了数据. 继承是为了重用父类代码,同时为实现多态性作 ...
- 学习上溯造型和下溯造型 【转载一篇】
题按:做了几年的java程序,却很难说对基本的OO概念都有理解.即便每天都写的代码中,也很难说清楚其中到底运用了怎样的概念和思想.前日的考试中看到关于上溯造型与下溯造型的问题,就查了些资料,集中说一下 ...
- 上溯造型和下溯造性(解耦合)
上溯造型: 向上转型(Upcasting)- 子类转换为父类,自动转换: 前提 - 具有继承或实现关系: 向上转换损失了子类新扩展的属性和方法,仅可以使用从父类中继承的属性和方法 Animal a=n ...
- Java的上溯、下溯
2019独角兽企业重金招聘Python工程师标准>>> 抽象方法:只有方法声明没有实现,有一个抽象方法的的类叫抽象类 修饰符: 例: abstract class Operator{ ...
最新文章
- SD卡中FAT32文件格式快速入门(图文详细介绍)
- Git篇——Git使用教程
- 面试官:Spring事务的传播行为有几种?
- 5、线程终止方式:pthread_cleanup_push/pthread_cleanup_pop()
- linux查询字段排序,Linux 操作命令 sort
- 关于strlwr,strupr等函数在此作用域中尚未声明的问题
- python集合类型变量_Python小白学习之路(八)—【变量】【基本数据类型分类】【集合】【集合的功能】...
- linux下怎么编译动态库并且调用
- 单边指数信号的特点_今日股市分析:上证指数若能守住3400,蓄力反弹就有戏...
- Android中CursorLoader的使用、原理及注意事项
- asp.net 页面右下角弹出类似QQ或MSN的消息提示
- 实习成长之路:操作系统——CPU有哪些工作模式呢?
- java计算机毕业设计计算机组成原理教学网站MyBatis+系统+LW文档+源码+调试部署
- 如何提升自己写代码的能力
- 盘扣架市场持续低迷,春节后是否能“破圈”?
- 初学者笔记:Scanf间隔符号的使用
- kali中rarcrack爆破rar压缩包密码
- 全网比较火的爱心代码
- 音视频开发系列1:音视频开发基本概念
- k3595参数_1高频三极管的一些型号及参数