一、对象转型介绍

  对象转型分为两种:一种叫向上转型(父类对象的引用或者叫基类对象的引用指向子类对象,这就是向上转型),另一种叫向下转型。转型的意思是:如把float类型转成int类型,把double类型转成float类型,把long类型转成int类型,这些都叫转型。把一种形式转成另外一种形式就叫转型。除了基础数据类型的转型之外(基础数据类型的转型:大的可以转成小的,小的也可以转成大的。),对象领域里面也有对象之间的转型。

1.1.对象转型实例一

  1 package javastudy.summary;
  2
  3 /**
  4  * 父类Animal
  5  * @author gacl
  6  *
  7  */
  8 class Animal {
  9
 10     public String name;
 11
 12     public Animal(String name) {
 13         this.name = name;
 14     }
 15 }
 16
 17 /**
 18  * 子类Cat继承Animal
 19  * @author gacl
 20  *
 21  */
 22 class Cat extends Animal {
 23
 24     /**
 25      * Cat添加自己独有的属性
 26      */
 27     public String eyeColor;
 28
 29     public Cat(String n, String c) {
 30         super(n);//调用父类Animal的构造方法
 31         this.eyeColor = c;
 32     }
 33 }
 34
 35 /**
 36  * 子类Dog继承Animal
 37  * @author gacl
 38  *
 39  */
 40 class Dog extends Animal {
 41     /**
 42      * Dog类添加自己特有的属性
 43      */
 44     public String furColor;
 45
 46     public Dog(String n, String c) {
 47         super(n);//调用父类Animal的构造方法
 48         this.furColor = c;
 49     }
 50
 51 }
 52
 53 /**
 54  * 下面是这三个类的测试程序
 55  * @author gacl
 56  *
 57  */
 58 public class TestClassCast {
 59
 60     /**
 61      * @param args
 62      */
 63     public static void main(String[] args) {
 64
 65         Animal a = new Animal("name");
 66         Cat c = new Cat("catname","blue");
 67         Dog d = new Dog("dogname", "black");
 68         /**
 69          * a instanceof Animal这句话的意思是a是一只动物吗?
 70          * a是Animal这个类里面的是一个实例对象,所以a当然是一只动物,其结果为true。
 71          */
 72         System.out.println(String.format("a instanceof Animal的结果是%s",a instanceof Animal));//true
 73         /**
 74          * c是Cat类的实例对象的引用,即c代表的就是这个实例对象,
 75          * 所以“c是一只动物”打印出来的结果也是true。
 76          * d也一样,所以“d是一只动物”打印出来的结果也是true。
 77          */
 78         System.out.println(String.format("c instanceof Animal的结果是%s",c instanceof Animal));//true
 79         System.out.println(String.format("d instanceof Animal的结果是%s",d instanceof Animal));//true
 80         /**
 81          * 这里判断说“动物是一只猫”,不符合逻辑,所以打印出来的结果是false。
 82          */
 83         System.out.println(String.format("a instanceof Cat的结果是%s",a instanceof Cat));
 84         /**
 85          * 这句话比较有意思了,a本身是Animal类的实例对象的引用,
 86          * 但现在这个引用不指向Animal类的实例对象了,而是指向了Dog这个类的一个实例对象了,
 87          * 这里也就是父类对象的引用指向了子类的一个实例对象。
 88          */
 89         a = new Dog("bigyellow", "yellow");
 90         System.out.println(a.name);//bigyellow
 91         /**
 92          * 这里的furColor属性是子类在继承父类的基础上新增加的一个属性,是父类没有的。
 93          * 因此这里使用父类的引用对象a去访问子类对象里面新增加的成员变量是不允许的,
 94          * 因为在编译器眼里,你a就是Animal类对象的一个引用对象,你只能去访问Animal类对象里面所具有的name属性,
 95          * 除了Animal类里面的属性可以访问以外,其它类里面的成员变量a都没办法访问。
 96          * 这里furColor属性是Dog类里面的属性,因此你一个Animal类的引用是无法去访问Dog类里面的成员变量的,
 97          * 尽管你a指向的是子类Dog的一个实例对象,但因为子类Dog从父类Animal继承下来,
 98          * 所以new出一个子类对象的时候,这个子类对象里面会包含有一个父类对象,
 99          * 因此这个a指向的正是这个子类对象里面的父类对象,因此尽管a是指向Dog类对象的一个引用,
100          * 但是在编译器眼里你a就是只是一个Animal类的引用对象,你a就是只能访问Animal类里面所具有的成员变量,
101          * 别的你都访问不了。
102          * 因此一个父类(基类)对象的引用是不可以访问其子类对象新增加的成员(属性和方法)的。
103          */
104         //System.out.println(a.furColor);
105         System.out.println(String.format("a指向了Dog,a instanceof Animal的结果是%s",a instanceof Animal));//true
106         /**
107          * 这里判断说“a是一只Dog”是true。
108          * 因为instanceof探索的是实际当中你整个对象到底是什么东西,
109          * 并不是根据你的引用把对象看出什么样来判断的。
110          */
111         System.out.println(String.format("a instanceof Dog的结果是%s",a instanceof Dog));//true
112         /**
113          * 这里使用强制转换,把指向Animal类的引用对象a转型成指向Dog类对象的引用,
114          * 这样转型后的引用对象d1就可以直接访问Dog类对象里面的新增的成员了。
115          */
116         Dog d1 = (Dog)a;
117         System.out.println(d1.furColor);//yellow
118     }
119
120 }

运行结果:

内存分析

  在内存中可以看到,指向Dog类实例对象的引用对象a是一个Animal类型的引用类型,这就比较有意思了,Animal类型指向了Dog这个对象,那么,在程序的眼睛里会把这只Dog当成一只普通的Animal,既然是把Dog当成一只普通的Animal,那么Dog类里面声明的成员变量furColor就不能访问了,因为Animal类里面没有这个成员变量。因此,从严格意义上来讲,这个a眼里只看到了这个子类对象里面的父类对象Animal,因此能访问得到的也只是这个Animal对象里面的name属性,而这个Animal对象外面的furColor属性是访问不到的,虽然Dog对象确实有这个属性存在,但a就是看不到,a门缝里看Dog——把Dog看扁了,不知道Dog还有furColor这个属性存在,因此a访问不了furColor属性,因此从严格意义上来讲,a指向的只是这个Dog对象里面的Animal对象,也就是黄色箭头指向的那部分,a就只看到了Dog里面这部分,而Dog外面的部分都看不到了。这就是父类引用指向子类对象,父类引用指向子类对象的时候,它看到的只是作为父类的那部分所拥有的属性和方法,至于作为子类的那部分它没有看到。

  如果真的想访问Dog对象的furColor属性,那就采用对象转型的办法,把父类对象的引用转型成子类对象的引用。Dog d1 = (Dog)a;这里采用的就是对象转型的办法,把a强制转换成一只Dog对象的引用,然后将这个引用赋值给Dog型的引用变量d1,这样d1和a都是指向堆内存里面的Dog对象了,而且d1指向的就是这只Dog所有的部分了,通过这个d1就可以访问Dog对象里面所有的成员了。

1.2.对象转型实例二

 1 public class TestClassCast {
 2
 3     public void  f(Animal a) {
 4         System.out.println(a.name);
 5         if (a instanceof Cat) {
 6             Cat cat = (Cat)a;
 7             System.out.println(cat.eyeColor+" eye");
 8         }else if (a instanceof Dog) {
 9             Dog dog = (Dog)a;
10             System.out.println(dog.furColor+" fur");
11         }
12     }
13
14     /**
15      * @param args
16      */
17     public static void main(String[] args) {
18         Animal a = new Animal("name");
19         Cat c = new Cat("catname","blue");
20         Dog d = new Dog("dogname", "black");
21         TestClassCast testClassCast = new TestClassCast();
22         testClassCast.f(a);
23         testClassCast.f(c);
24         testClassCast.f(d);
25     }
26 }

  这里的这些代码是对前面声明的三个类Animal,Dog,Cat测试的延续,这里我们在TestClassCast这里类里面测试这个三个类,这里我们在TestClassCast类里面new了一个testClassCast对象,为的是调用TestClassCast类里面声明的f(Animal  a)这个方法,这个f()方法里面的参数类型是Animal类型,如果是Animal类型的参数,那么我们可以把这个Animal类型的子类对象作为参数传进去,这是可以的。如把一只Dog或者是一只Cat丢进f()方法里面这都是可以的,因为Dog和Cat也是Animal。因此当程序执行到testClassCast.f(a);,testClassCast.f(c);,testClassCast.f(d);的时候,因为f()方法里面的参数是Animal类型的,所以我们可以把一个Animal对象传进去,除此之外,我们还可以直接把从Animal类继承下来的Dog类和Cat类里面的Dog对象和Cat对象作为实参传递过去,即是把Animal类型的子类对象作为参数传进去。这里就体现出了继承和父类对象的引用可以指向子类对象的好处了,如果说没有继承关系的存在,如果说父类的引用不可以指向子类对象,那么我们就得要在Test类里面定义三个f()方法了,即要定义这样的f()方法:
f(Animal a)、f(Dog d)、f(Cat c)分别用来处理Animal、Dog和Cat,使用三个方法来处理,将来程序的扩展起来就不是很容易了,因为面向对象可以帮助我们这些年来编程苦苦追求的一个境界是可扩展性比较好。可扩展性比较好的一个典型例子就是说当你建好一个建筑之后或者是你写好这个程序之后,把这个主建筑给建好了,将来你要加一些其他的功能的时候,尽量不要去修改主结构,这叫可扩展性好,你盖了一座大楼,你现在要在大楼的旁边添加一个厨房,那你在它旁边一盖就行了,如果有人告诉你,我添加一个厨房我需要把你整个大楼的主要柱子都给拆了然后再盖一遍,这你干吗,肯定不干。如果结构设计成这样,那就是设计得不好,可扩展性不好。所以这里如果要把f()方法写成三个重载的f()方法,那么将来我输出一只鸟的时候又得要添加一个f(Bird  b)方法来处理鸟。这样扩展起来就太麻烦了,因为每处理一只动物都要添加一个新的方法,但是如果存在继承关系,如果父类对象的引用可以指向子类对象,那扩展起来就简单了,你可以把处理动物的方法写在一个方法f(Animal  a)里面就够了,因为所有动物的种类都是从Animal类继承下来,因此给f()方法传递Animal类型的参数的时候可以直接把这个Animal类的子类对象传进去,这样不管是要增加什么动物的输出,我都可以调用f(Animal a)方法去处理,这种扩展性比每次都要增加一个新的处理方法的扩展性要好得多,这就是继承的一个好处,这就是对象转型对于可扩展性来的好处:“对象的引用可以指向子类对象”,是因为面向对象的编程里面存在这样的继承关系,使得程序的可扩展性比较好。

  对象转型可以使父类对象的引用可以指向子类对象,给程序带来了比较好的可扩展性:我们可以在一个方法的参数里面定义父类的引用,然后实际当中传的时候传的是子类的对象,然后我们再在方法里面判断这个传过来的子类对象到底属于哪个子类,然后再去执行这个子类里面的方法或者调用这个子类里面的成员变量,因此程序的可扩展性比单独定义好多个方法要好一些。不过这个可扩展性还没有达到最好,使用多态就可以让程序的扩展性达到极致。

转载于:https://www.cnblogs.com/xdp-gacl/p/3647810.html

java基础学习总结——对象转型相关推荐

  1. java基础学习之对象转型

    对象转型(casting): 1)一个基类的引用类型变量可以指向其子类的对象 2)一个基类的引用不可以访问其子类对象新增加的成员(属性和方法) 3)可以使用引用变量instanceof类名,来判断该引 ...

  2. Java基础学习:尚硅谷项目三 开发团队调度软件

    Java基础学习:尚硅谷项目三 开发团队调度软件 一.软件功能与结构设计 1. 软件功能 该软件实现以下功能: 软件启动时,根据给定的数据创建公司部分成员列表(数组) 根据菜单提示,基于现有的公司成员 ...

  3. JAVA基础学习--面向对象

    JAVA基础学习–面向对象 1.面向对象与面向过程: 面向过程:就代表从头到位,每一步都需要我们来完成,例如洗衣服,首先收拾脏衣服.接上水.到洗衣液.搓.倒水.拧干.晾晒.每一步都需要我们来完成. 面 ...

  4. java基础学习整理(一)

    java基础学习整理(一) lesson1: D0s命令: 1.回到根目录,>cd \ 2.复制命令行下的内容,右击标记所要复制的内容,这样就已经复制好了,右击粘贴就可以了. 3.查看,设置环境 ...

  5. 【Java基础学习笔记】- Day11 - 第四章 引用类型用法总结

    Java基础学习笔记 - Day11 - 第四章 引用类型用法总结 Java基础学习笔记 - Day11 - 第四章 引用类型用法总结 4.1 class作为成员变量 4.2 interface作为成 ...

  6. Java中大数据数组,Java基础学习笔记之数组详解

    摘要:这篇Java开发技术栏目下的"Java基础学习笔记之数组详解",介绍的技术点是"java基础学习笔记.基础学习笔记.Java基础.数组详解.学习笔记.Java&qu ...

  7. 尚学堂JAVA基础学习笔记_2/2

    尚学堂JAVA基础学习笔记_2/2 文章目录 尚学堂JAVA基础学习笔记_2/2 写在前面 第10章 IO技术 1. IO入门 2. IO的API 3. 装饰流 4. IO实战 5. CommonsI ...

  8. Java基础学习——第十四章 网络编程

    Java基础学习--第十四章 网络编程 一.网络编程概述 计算机网络: 把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大.功能强的网络系统,从而使众多的计算机可以方便地互相传递信 ...

  9. Java基础学习(9)

    Java基础学习 一.常用方法(API) 1.1 Math 1.2 System 1.3 Runtime 1. 4 .object 1.5 Objects 1.6 BigInteger BigInte ...

最新文章

  1. 数据结构之Treap
  2. python之pygame安装教程_Python中pygame安装方法图文详解
  3. mysql 添加用户_mysql创建用户与授权
  4. SVN系列操作(一)
  5. dash 和 bash 切换
  6. Linux C代码实现读取配置文件示例
  7. Convert Sorted Array to Binary Search Tree With Minimal Height
  8. 你应该关注的几个Eclipse超酷插件
  9. uwsgi怎么启动停止
  10. java 发送支持超链接的邮件
  11. adobe reader XI 打开后闪退(或过几秒后自动退出)【终极解决方案】
  12. 硬件编码相关知识(H264,H265)
  13. c语言三阶素数魔方阵,C语言 三阶魔方阵
  14. javascript中ready和onload的理解
  15. 《平衡掌控者 游戏数值战斗设计》学习笔记(五)物品掉落
  16. win10 如何使用命令简单的禁用自带键盘
  17. 室内定位的电子地图编辑工具
  18. 不站队的UCloud,才是最可怕的
  19. npm-run-all 同时运行多条命令
  20. 本体推理中jess和jena区别

热门文章

  1. java的model层实例_Struts 2.1.6 精简实例系列教程(3):新闻管理Model层的开发(整合iBatis)...
  2. php switch 函数,PHP丨PHP基础知识之条件语SWITCH判断「理论篇」
  3. CCNA必会知识点:路由器PAP单向认证怎么配置?
  4. 课程升级 | 极速构建知识体系,即学即用 Serverless
  5. 6 张图带你彻底搞懂分布式事务 XA 模式
  6. 阿里巴巴开源容器镜像加速技术
  7. 云原生五大趋势预测,K8s 安卓化位列其一
  8. linux运维技巧,Linux运维需要掌握的17个实用技巧
  9. tp5获取mysql版本_TP5 + MySQL 应用地址选择
  10. 拖链电缆 机器人电缆_洞头高柔性拖链网线标柔电缆