1.前言
在谈转型之前我们需要了解,关于引用变量的类型和具体实例之间的关系.
举个例子:

public class Person {protected String name;protected Integer age;//在构建属性和方法的时候需要注意,访问权限控制符.需要能够被子类所访问到.//public 公开的,本模块内所有的包都可以访问.  protect 本类,同包,子类,子类包. defailt 默认,同一个包. private 本类.//通过构造器初始化赋值public Person(){name ="personName";age =24;}void sayHello(){System.out.println("sayHello 名字:"+name+" 年龄:"+age);}void sayGood(){System.out.println("sayGood 名字:"+name+" 年龄:"+age);}
}
Person person = new Person();

上面一行的代码的含义,左边的new Person(); 也就是调用构造方法是以Person类为模板新建了一个对象.左边的Person person 意思是声明一个引用变量,这个变量的名字叫 person ,类型是Person ,他说指引的对象实例,就是右边刚刚创建出来的那个实例.

如果使用person去做某件事情,调用一个方法,例如person.sayHello();那么实际上是他所指引的对象实例在具体操作,他本身也就是说 引用变量本身person 并不具有什么行为属性.因为他不是一个实体,他就是一个遥控器,里面是他所指引对象的在内存中的地址.

而他能够指引哪些对象呢,也是有规定的,不是所有对象他都能够去指引(去遥控),是需要和他的类型相匹配.是的,这个引用变量也是有一个类型.相当于他的身份,他有了这个身份才能去指引 对应的对象实例,然后遥控对象实例进行操作.

2.向上转型

2.1 构建子类

public class Student extends Person {protected Integer studentNum;//学号 学生子类特有的//通过构造器初始化 赋值Student(){name ="ling"; //对继承父类的属性重新 赋值studentNum = 18599306; //给子类自己特有的属性赋值}@Overridevoid sayGood() {// super.sayGood(); 不使用父类的方法 我们来重写他的方法System.out.println("Student sayGood 名字:"+name+" 年龄:"+age+" 学号:"+studentNum);}//添加子类特有方法void doStudy(){System.out.println("我是一名学生,我的爱好是喝花酒:"+name+" 年龄:"+age+" 学号:"+studentNum);}
}

2.2在向上转型之前,我们需要明白我们为什么要这么做.那么我们可以看看在不做向上转型之前,父类类型引用和子类类型引用各自可以做哪些事情.

public class Hello {public static void main(String[] args) {Person person =new Person();Integer age = person.age;String name = person.name;person.sayGood();person.sayHello();System.out.println("Person打印 年龄:"+age+" 名字:"+name);//可以看到 使用父类引用变量和父类实例 可以访问父类里面的所有属性. }
}

打印如下

sayGood 名字:personName 年龄:24
sayHello 名字:personName 年龄:24
Person打印 年龄:24 名字:personName
//同理 我们来尝试使用子类引用变量 和 子类实例访问
Student student =new Student();
String name1 = student.name;
Integer age1 = student.age;
Integer studentNum = student.studentNum;
student.sayGood();
student.sayHello();
student.doStudy();
System.out.println("Student打印 名字:"+name+"年龄"+age+"学号"+studentNum);

打印如下

Student sayGood 名字:ling 年龄:24 学号:18599306
sayHello 名字:ling 年龄:24
我是一名学生,我的爱好是喝花酒:ling 年龄:24 学号:18599306
Student打印 名字:ling年龄24学号18599306

我们可以看到,继承父类的属性,如果没有被修改则被保留 例如age.修改后,就被覆盖掉了 例如name,sayGood().而自己访问自己特有的属性和方法那是肯定没有问题的 例如studentNum,doStudy();.

但是如果我想使用父类的引用变量访问自己已经被改造的方法呢.(本身是自己有的,但是被子类改造了,访问改造后的),我们来试一下.

    // 当我尝试使用父类引用和实例 直接访问子类特有的属性和方法时,编译报错了.person.studentNum;person.doStudy();

报错为 Cannot resolve symbol ‘studentNum’ ,经过我千帆万苦使用翻译后说是 无法解析符号.也就是找不到这样的属性或者方法.
我抽了一根烟,长叹一声"老天爷,你为什么要这样对我!!"
说时迟那时快,我想起了 前言中我们提到的那个概念.引用类型变量本身是一个遥控器,他本身不具备属性和行为,而我们使用 父类类型引用变量 Person person,是遥控 new Person(); 这个对象,然后去操作他子类对象实例才有的东西,这不是笑话吗?
呜呼哉!天不亡我,命不该如此.

2.3 办法就是 我们使用父类类型引用变量 Person p去 遥控子类实例 new Student();操作子类实例自身的属性和方法,岂不美哉.
Person p = new Student();

 Person p = new Student();String name2 = p.name;Integer age2 = p.age;p.sayGood();p.sayHello();System.out.println("Student类型转换 向上转型 打印 名字:"+name2+"年龄"+age2+"学号");//同时 这里的限定是 只能访问父类 类型里面的属性,不能访问子类特有的

打印如下

Student sayGood 名字:ling 年龄:24 学号:18599306
sayHello 名字:ling 年龄:24
Student类型转换 向上转型 打印 名字:ling年龄24学号

可以看出,这时候父类引用变量已经可以访问自己被子类改造后的属性和方法.之所以访问不了子类特有的属性和方法,是因为我们之前提到的.引用类型变量,他有身份.他的身份就是他的类型.现在他的类型是Person类型,如果想要让他光明正大的访问子类类型特有属性和方法,那么需要加钱,哦,不!需要类型转换.转为Student类型.由于是从父类转化到子类所以称之为向下转型.

3.向下转型

 Student s = (Student) p; //向下转型需要使用强制类型转换String name3 = s.name;Integer age3 = s.age;Integer studentNum1 = s.studentNum;s.sayHello();s.sayGood();s.doStudy();System.out.println("Person p 向下转型 名字:"+name3+"年龄"+age3+"学号"+studentNum1);

打印如下

sayHello 名字:ling 年龄:24
Student sayGood 名字:ling 年龄:24 学号:18599306
我是一名学生,我的爱好是喝花酒:ling 年龄:24 学号:18599306
Person p 向下转型 名字:ling年龄24学号18599306

由此可见,转型成为Student s后,s就可以愉快的访问各自私密信息啦啦啦啦.
现在我们来回顾一下.
1)使用父类类型,扩展性特别强,但是我们想访问被子类改造后的属性和方法,就需要向上转型.这个含义是 一个子类实例s0,被 一个父类引用变量Person p所指引了.本质上进行操作的还是子类实例s0,只不过遥控器的身份更加是父类引用.
2)而当我们在此时,还是需要进一步访问子类实例s0的自身特殊属性和方法时候,那么我们需要把 刚刚s0这个实例对象,使用一个子类类型的引用变量Student s来进行操作,这样才可以访问到自身特殊的信息.而这个实例s0的引用变量从Person p到Student s的变化过程中,我们称之为向下转型.
3)我们看到在这个过程中,实例对象自始至终都是s0本身,没有发生变化只是在创建后引用由一般默认的同级别的子类引用,变成了父类引用,向上造型.而从父类引用又变成子类引用.向下造型.
4)那么我们思考,反过来可以吗?

4.关于类型转换
4.1 从大到小 or 从小到大

       Student s10 =new Student();Person p10 = new Person();boolean flag = p10 instanceof Student;//实际上之前的操作有些不那么严谨,在类型转换之前需要进行判断//如果可以就转,如果不能转,强转的话会出现运行异常,编译是没有问题的.// instanceof是Java中的二元运算符,左边是对象,右边是类;当对象是右边类或子类所创建对象时,返回true;否则,返回false。//只有flag为true的时候,才能把p10强转为Student类型.System.out.println("flag:"+flag);if(flag){s10= (Student) p10;  //强制类型转换 String name4 = s10.name;System.out.println("名字:"+name4);}

打印如下

flag:false

由此可见,一个父类实例对象是不能把 引用变量变成子类引用变量的.相当于一个大胖子,试图把身上的衣服从大号的换成小号的.
我们知道Java是人设计出来的东西,为何小转大可以,大转小就不可以呢,这里就要提到一个理论.
里氏替换原则:在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象。
例如:狗 田园犬
我家里有一条田园犬,那么可以推断我家里有一条狗.
反之,我家里有一条狗,不能推断出成我家里有一条田园犬.

里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。

浅析向上转型和向下转型相关推荐

  1. java中向上转型和向下转型浅析

    基础概念 向上转型就是子类对象被父类引用,例如动物和小鸟的关系,小鸟属于动物,动物不仅仅只包含小鸟,还包含猫和狗等,例如: Animal  birdAnimal = new Bird();这种方式就是 ...

  2. 【Java挠头】继承、抽象、接口、多态、向上转型、向下转型等精妙干货

    –本文摘要–     1.本文的目标读者:是了解Java基础,且对面向对象概念有所了解,但是对Java中继承.抽象类.接口.多态等等概念搞不清的初学者.     2.本文的内容摘要:讲述Java中的一 ...

  3. 重新精读《Java 编程思想》系列之向上转型与向下转型

    前言 今天重读了一下向上转型与向下转型,有些新的体会,了解了向上转型的好处,及如何向下转型.在此分享给大家. 向上转型 向上转型是用来表现新类和基类之间的关系.在传统中,由导出类转型成基类,在继承图中 ...

  4. Day11多态部分-6 【1.3 对象的向上转型和向下转型】

    [1.3 对象的向上转型和向下转型] + - 向上转型 子类对象赋值给父类类型的引用时 会自动将子类对象对应的类型 提升为父类类型 语法: 父类类型 引用 = new 子类的构造方法(); 特点: 此 ...

  5. 第三次学JAVA再学不好就吃翔(part35)--多态向上转型和向下转型

    学习笔记,仅供参考 文章目录 面向对象 多态 多态向上转型和向下转型 多态的好处和弊端 面向对象 多态 多态向上转型和向下转型 我们首先通过以下代码复习一下自动类型提升和强制类型转换: class B ...

  6. Java转型(向上转型和向下转型)

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

  7. 【转】面向对象之多态(向上转型与向下转型)

    转:https://blog.csdn.net/qq_31655965/article/details/54746235. 多态,大概每个人都知道.但是,又有几个人真的理解什么是多态.多态有哪些细节呢 ...

  8. 三分钟带你搞懂什么是向上转型和向下转型

    什么是向上转型? 通过在网上查了资料,和普遍的介绍,一句话总结就是"父类引用指向子类对象",例: Human h=new Human(); h.eat();//人类 Animal ...

  9. [JAVA]向上转型与向下转型

    要理解多态性,首先要知道什么是"向上转型"."向下转型". 对象的多态性:父子类对象的转换 **向上转型:**子类对象变为父类对象,语法: 父类 父类对象 = ...

最新文章

  1. pycharm的安装配置和简单使用
  2. Android学习笔记18:自定义Seekbar拖动条式样
  3. ML:机器学习中与模型相关的一些常见的判断逻辑(根据自调整阈值计算阳性率)
  4. Python中必学知识点:类方法、实例方法和静态方法
  5. [react] 为什么建议Fragment包裹元素?它的简写是什么?
  6. 前端学习(2907):Vite的特点
  7. Processing 闪烁的圆 动画效果
  8. python3 换源_CentOS 7.5 下 python3 安装及 pip 换源
  9. python判断奇数_python 中x%2 x1 判断偶数奇数 性能对比
  10. 回溯法采用的搜索策略_急性阑尾炎最典型的症状为:
  11. 亲历!给大龄IT人的几点求职建议
  12. 从 1 到完美,用 node 写一个命令行工具
  13. CTO 深度解读 SMTX OS 3.5 产品特性
  14. 海量数据处理--大数据处理概论
  15. 硬编码支持情况(一)
  16. 周末做了一个区块链导航工具-Barfor导航
  17. 7年时间,从功能测试到测试开发月薪30K,有志者事竟成
  18. [Android]Toolbar
  19. python什么证书最有价值,python哪个证书含金量高
  20. java 取款机_JAVA ATM提款机程序

热门文章

  1. 职工信息管理系统c语言报告,职工信息管理系统(c语言实现)
  2. 【求职】 网易 2018 校园招聘 Java 开发工程师(BJ)笔试卷
  3. 《在路上 …》 42区介绍演讲- 在家的排练的MP3
  4. 穹顶灯打不出阴暗面_微服务的阴暗面,解释
  5. AVS+标准应用现状
  6. 常见拉丁文读法,肯定用得着~
  7. 2.控制结构(选择、循环)
  8. 为字体文件增添自定义图标
  9. 什么是画中画模式,画中画视频怎么操作
  10. springboot项目中使用Echarts实现数据折现可视化