在Java编程中经常碰到类型转换,对象类型转换主要包括向上转型和向下转型。

5.13.1 向上转型

我们在现实中常常这样说:这个人会唱歌。在这里,我们并不关心这个人是黑人还是白人,是成人还是小孩,也就是说我们更倾向于使用抽象概念“人”。再例如,麻雀是鸟类的一种(鸟类的子类),而鸟类则是动物中的一种(动物的子类)。我们现实中也经常这样说:麻雀是鸟。这两种说法实际上就是所谓的向上转型,通俗地说就是子类转型成父类。这也符合Java提倡的面向抽象编程思想。来看下面的代码:

package a.b;

public class A {

public void a1() {

System.out.println("Superclass");

}

}

A的子类B:

package a.b;

public class B extends A {

public void a1() {

System.out.println("Childrenclass"); //覆盖父类方法

}

public void b1(){} //B类定义了自己的新方法

}

C类:

package a.b;

public class C {

public static void main(String[] args) {

A a = new B(); //向上转型

a.a1();

}

}

如果运行C,输出的是Superclass 还是Childrenclass?不是你原来预期的Superclass,而是Childrenclass。这是因为a实际上指向的是一个子类对象。当然,你不用担心,Java虚拟机会自动准确地识别出究竟该调用哪个具体的方法。不过,由于向上转型,a对象会遗失和父类不同的方法,例如b1()。有人可能会提出疑问:这不是多此一举吗?我们完全可以这样写:

B a = new B();

a.a1();

确实如此!但这样就丧失了面向抽象的编程特色,降低了可扩展性。其实,不仅仅如此,向上转型还可以减轻编程工作量。来看下面的显示器类Monitor:

package a.b;

public class Monitor{

public void displayText() {}

public void displayGraphics() {}

}

液晶显示器类LCDMonitor是Monitor的子类:

package a.b;

public class LCDMonitor extends Monitor {

public void displayText() {

System.out.println("LCD display text");

}

public void displayGraphics() {

System.out.println("LCD display graphics");

}

}

阴极射线管显示器类CRTMonitor自然也是Monitor的子类:

package a.b;

public class CRTMonitor extends Monitor {

public void displayText() {

System.out.println("CRT display text");

}

public void displayGraphics() {

System.out.println("CRT display graphics");

}

}

等离子显示器PlasmaMonitor也是Monitor的子类:

package a.b;

public class PlasmaMonitor extends Monitor {

public void displayText() {

System.out.println("Plasma display text");

}

public void displayGraphics() {

System.out.println("Plasma display graphics");

}

}

现在有一个MyMonitor类。假设没有向上转型,MyMonitor类代码如下:

package a.b;

public class MyMonitor {

public static void main(String[] args) {

run(new LCDMonitor());

run(new CRTMonitor());

run(new PlasmaMonitor());

}

public static void run(LCDMonitor monitor) {

monitor.displayText();

monitor.displayGraphics();

}

public static void run(CRTMonitor monitor) {

monitor.displayText();

monitor.displayGraphics();

}

public static void run(PlasmaMonitor monitor) {

monitor.displayText();

monitor.displayGraphics();

}

}

可能你已经意识到上述代码有很多重复代码,而且也不易维护。有了向上转型,代码可以更为简洁:

package a.b;

public class MyMonitor {

public static void main(String[] args) {

run(new LCDMonitor());                     //向上转型

run(new CRTMonitor());                     //向上转型

run(new PlasmaMonitor());            //向上转型

}

public static void run(Monitor monitor) { //父类实例作为参数

monitor.displayText();

monitor.displayGraphics();

}

}

我们也可以采用接口的方式,例如:

package a.b;

public interface Monitor {

abstract void displayText();

abstract void displayGraphics();

}

将液晶显示器类LCDMonitor稍作修改:

package a.b;

public class LCDMonitor implements Monitor {

public void displayText() {

System.out.println("LCD display text");

}

public void displayGraphics() {

System.out.println("LCD display graphics");

}

}

CRTMonitor、PlasmaMonitor类的修改方法与LCDMonitor类似,而MyMonitor可以不不作任何修改。

可以看出,向上转型体现了类的多态性,增强了程序的简洁性。

5.13.2 向下转型

子类转型成父类是向上转型,反过来说,父类转型成子类就是向下转型。但是,向下转型可能会带来一些问题:我们可以说麻雀是鸟,但不能说鸟就是麻雀。来看下面的例子:

A类:

package a.b;

public class A {

void aMthod() {

System.out.println("A method");

}

}

A的子类B:

package a.b;

public class B extends A {

void bMethod1() {

System.out.println("B method 1");

}

void bMethod2() {

System.out.println("B method 2");

}

}

C类:

package a.b;

public class C {

public static void main(String[] args) {

A a1 = new B(); // 向上转型

a1.aMthod();    // 调用父类aMthod(),a1遗失B类方法bMethod1()、bMethod2()

B b1 = (B) a1; // 向下转型,编译无错误,运行时无错误

b1.aMthod();    // 调用父类A方法

b1.bMethod1(); // 调用B类方法

b1.bMethod2(); // 调用B类方法

A a2 = new A();

B b2 = (B) a2; // 向下转型,编译无错误,运行时将出错

b2.aMthod();

b2.bMethod1();

b2.bMethod2();

}

}

从上面的代码我们可以得出这样一个结论:向下转型需要使用强制转换。运行C程序,控制台将输出:

Exception in thread "main" java.lang.ClassCastException: a.b.A cannot be cast to a.b.B at
                a.b.C.main(C.java:14)

A method

A method

B method 1

B method 2

其实黑体部分的向下转型代码后的注释已经提示你将发生运行时错误。为什么前一句向下转型代码可以,而后一句代码却出错?这是因为a1指向一个子类B的对象,所以子类B的实例对象b1当然也可以指向a1。而a2是一个父类对象,子类对象b2不能指向父类对象a2。那么如何避免在执行向下转型时发生运行时ClassCastException异常?使用5.7.7节学过的instanceof就可以了。我们修改一下C类的代码:

A a2 = new A();

if (a2 instanceof B) {

B b2 = (B) a2;

b2.aMthod();

b2.bMethod1();

b2.bMethod2();

}

这样处理后,就不用担心类型转换时发生ClassCastException异常了。

转载于:https://www.cnblogs.com/wangtianze/p/6691216.html

Java转型(向上转型和向下转型)相关推荐

  1. 9.什么是向上转型?什么是向下转型?

    向上转型: 一般来说就是: 父类引用指向子类对象,是多态实现的一个基础.也就是说,父类引用可以自动地包装子类对象.例如:Student类 继承了 Person 类 Person person = ne ...

  2. Java转型(向上或向下转型)

    在Java编程中经常碰到类型转换,对象类型转换主要包括向上转型和向下转型. 5.13.1 向上转型 我们在现实中常常这样说:这个人会唱歌.在这里,我们并不关心这个人是黑人还是白人,是成人还是小孩,也就 ...

  3. java 强制向上转型,Java 转型(向上或向下转型)详解及简单实例

    在Java编程中经常碰到类型转换,对象类型转换主要包括向上转型和向下转型. 向上转型 我们在现实中常常这样说:这个人会唱歌.在这里,我们并不关心这个人是黑人还是白人,是成人还是小孩,也就是说我们更倾向 ...

  4. java向上和向下的区别_Java的向上和向下转型

    在Java编程中经常碰到类型转换,对象类型转换主要包括向上转型和向下转型. 向上转型 我们在现实中常常这样说:这个人会唱歌.在这里,我们并不关心这个人是黑人还是白人,是成人还是小孩,也就是说我们更倾向 ...

  5. Java向上转型 向下转型

    java转型,只要记住一句话:父类引用子类对象. 向上转型(upcasting),向下转型(downsasting). 例如:有两个类,Animal是父类,cat是子类. Animal an=new ...

  6. java 向下转型运行时错误_Java向上转型和向下转型

    首先定义父类Animal,所有动物都有一个吃东西的方法:子类Dog还增加了一个叫的功能. public classAnimal {public voideat() { System.out.print ...

  7. 【java基础18:方法覆盖与多态】什么时候使用方法覆盖 toString方法的覆盖 多态的基础语法与作用 向上/向下转型

    目录 方法覆盖Override 多态 方法覆盖Override 方法覆盖初体验,什么样的程序要方法覆盖 /*当前程序存在的问题(设计上的问题)??鸟儿在执行move()方法的时候,最好输出的结果是:& ...

  8. Java 面向对象编程(三)——多态,方法重写,向上转型,向下转型

    所谓多态,就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪 ...

  9. Java学习之向上、下转型

    需要注意的是向上.向下转型之后各个成员变量值的变化 首先来看父类代码 public class Quadrangle {public int rangle=30;public void doit() ...

最新文章

  1. 计算机网络分类(按覆盖范围分类)“名称、范围”
  2. ECLIPSE 调试F8-------运行到下一断点处 F5-------STEP INTO F6-------STEP OVER
  3. 记录SQL server学习的存储过程的摘录
  4. vscode 调试_如何使用VSCode调试JS?
  5. php基础教程 第十一步 面向对象
  6. Taro+react开发(71):Taro.nextTick
  7. 带负荷测试要求二次最小电流_差动保护带负荷测试
  8. sum() over (order by )
  9. 顶会集结+深度解析:医疗+AI如此火爆,NLP如何赋能?
  10. 【转】深入理解Java:SimpleDateFormat安全的时间格式化
  11. 制作唐诗网页代码_有关于诗词的网页代码
  12. 中通hadoop去CDH的实践之路
  13. Python自动化 requests 库:发送 form-data 格式的 http 请求
  14. Python的模块和包管理
  15. Spark 高难度对话 SQL Server 续篇
  16. java method field_java_解析Java中的Field类和Method类,Field类 Field类中定义了一些方 - phpStudy...
  17. CRM系统概念与项目开发流程
  18. LVGL笔记10--lv_cont容器
  19. ACM程序设计大赛概况
  20. jsp文字上下居中显示_怎么把jsp的文字居中

热门文章

  1. 微信网页授权,并获取用户头像,昵称等基本信息代码实例
  2. oncreate为什么一定要调用父类的oncreat_为什么你老是讲不清楚JS的继承模式
  3. tomcat 优化_浅谈Tomcat服务器优化方法
  4. CentOS7 安装 Nginx PHP
  5. 稳压电源的设计与制作_电子爱好设计的直流可调压电源电路,太完美了,有图,亲测可用...
  6. MySQL笔记-删除session,删除阻塞任务
  7. Java笔记-加密应用在网络通信中的使用
  8. Java笔记-模拟QQ三方登录(单点登录2.0)
  9. Qt文档阅读笔记-easingCurve:QEasingCurve官方解析及实例
  10. Python中操作mysql的pymysql模块详解