Java基础学习总结(4)——对象转型
一、对象转型介绍
对象转型分为两种:一种叫向上转型(父类对象的引用或者叫基类对象的引用指向子类对象,这就是向上转型),另一种叫向下转型。转型的意思是:如把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)方法去处理,这种扩展性比每次都要增加一个新的处理方法的扩展性要好得多,这就是继承的一个好处,这就是对象转型对于可扩展性来的好处:“对象的引用可以指向子类对象”,是因为面向对象的编程里面存在这样的继承关系,使得程序的可扩展性比较好。
对象转型可以使父类对象的引用可以指向子类对象,给程序带来了比较好的可扩展性:我们可以在一个方法的参数里面定义父类的引用,然后实际当中传的时候传的是子类的对象,然后我们再在方法里面判断这个传过来的子类对象到底属于哪个子类,然后再去执行这个子类里面的方法或者调用这个子类里面的成员变量,因此程序的可扩展性比单独定义好多个方法要好一些。不过这个可扩展性还没有达到最好,使用多态就可以让程序的扩展性达到极致。
Java基础学习总结(4)——对象转型的更多相关文章
- java基础学习总结六(对象与类、类的属性与方法)
一:面向过程与面向对象的区别 举例:一个人开门的动作,可以分解为开门,人进去,关门. 面向过程:人作为执行者,1:开门 2:进入 3:关门 面向对象:人作为指挥者,将开门,关门的动作都封装到门上 ...
- 转载-java基础学习汇总
共2页: 1 2 下一页 Java制作证书的工具keytool用法总结 孤傲苍狼 2014-06-24 11:03 阅读:25751 评论:3 Java基础学习总结——Java对象的序列化和 ...
- 尚学堂JAVA基础学习笔记
目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...
- Java基础学习笔记总结
Java基础学习笔记一 Java介绍 Java基础学习笔记二 Java基础语法之变量.数据类型 Java基础学习笔记三 Java基础语法之流程控制语句.循环 Java基础学习笔记四 Java基础语法之 ...
- JAVA基础学习-集合三-Map、HashMap,TreeMap与常用API
森林森 一份耕耘,一份收获 博客园 首页 新随笔 联系 管理 订阅 随笔- 397 文章- 0 评论- 78 JAVA基础学习day16--集合三-Map.HashMap,TreeMap与常用A ...
- [转帖]java基础学习总结——多态(动态绑定)
https://www.cnblogs.com/xdp-gacl/p/3644035.html 多态的概念 java基础学习总结——多态(动态绑定) 一.面向对象最核心的机制——动态绑定,也叫多态
- Java基础学习(2)
Java基础学习(二) 面向对象 对象:客观存在的事物 面向对象:人具体关注的事物的某些信息 类:是模子,确定对象会拥有的特征(属性)和行为(方法) 对象的属性:对象具有的各种特征 对象的方法:对象能 ...
- Java基础学习(4)
Java基础学习(四) String类 特点:创建后不可再修改,看起来的修改只是创建了新的对象 常用方法 StringBuilder类 目的:解决String类频繁创建对象的问题 常用方法 特点:非线 ...
- Java基础学习-- 继承 的简单总结
代码参考:Java基础学习小记--多态 为什么要引入继承? 还是做一个媒体库,里面可以放CD,可以放DVD.如果把CD和DVD做成两个没有联系的类的话,那么在管理这个媒体库的时候,要单独做一个添加CD ...
- Java基础学习中一些词语和语句的使用
在Java基础学习中,我们刚接触Java会遇到一些词和语句的使用不清的情况,不能很清楚的理解它的运行效果会是怎么样的,如:break,continue在程序中运行效果及跳转位置, 1.先来看看brea ...
随机推荐
- BZOJ 1415 [NOI2005]聪聪与可可 (概率DP+dfs)
题目大意:给你一个无向联通图,节点数n<=1000.聪聪有一个机器人从C点出发向在M点的可可移动,去追赶并吃掉可可,在单位时间内,机器人会先朝离可可最近的节点移动1步,如果移动一步机器人并不能吃 ...
- linux下为firfox安装flash player
1.去官网下载×.tar.gz包,如:flash_player_npapi_linux.x86_64.tar.gz 2.解压 tar -zxvf flash_player_npapi_linux.x8 ...
- python3三级菜单的访问,并按q退出
#/usr/bin/env python#yehui'''作业三:多级菜单 三级菜单 可依次选择进入各子菜单 所需新知识点:列表.字典'''import readlineclass MultiLeve ...
- Hibernate类没有找到序列化器解决方案
Hibernate类没有找到序列化器解决方案 异常信息类似如下 No serializer found for class org.hibernate.proxy.pojo.javassist.Jav ...
- 关于Vue实例的生命周期(2)
关于Vue实例的生命周期(2) 创建(create)->挂载(mount)->更新(update)->销毁(destory) 钩子函数触发事件 beforeCreate 在实例初始 ...
- Jenkins学习总结(5)——免费DevOps开源工具简介
一:开发工具 1.版本控制系统 Git Git是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常大的项目版本管理. 2.代码托管平台 GitLab GitLab是一个利用Ruby on ...
- ASP.NET-权限管理五张表
ASP.NET 权限管理五张表 权限管理的表(5张表) 每个表里面必有的一些信息 序号 名称 字段 类型 主键 默认值 是否为空 备注 1 用户ID ID INT 是 ...
- IntelliJ IDEA could not autowire no beans of 'Decoder'
IntelliJ IDEA could not autowire no beans of 'Decoder' 学习了:http://blog.csdn.net/u012453843/article/ ...
- C#一个托付的样例
C#中的函数能够被声明的一个托付所调用. 函数为静态方法.和托付声明的參数返回值要一致. class Program { delegate float MathOperationDelegate( ...
- Linux文件查找命令具体解释-which whereis find locate
原创BLog.转载请注明出处 http://blog.csdn.net/hello_hwc? viewmode=contents which命令 首先查看man which的说明 which - sh ...