详细讲述Java中的对象转型
作者:laozhang 发布时间:2023-09-24 04:09:49
标签:Java,对象转型
向上转型:子类对象转为父类,父类可以是接口。公式:Father f = new Son();Father是父类或接口,son是子类。
向下转型:父类对象转为子类。公式:Son s = (Son)f;
我们将形参设为父类Animal类型,当执行test.f(c)时,内存情况如下图:
c作为Cat类型传入,Animal a作为形参,相当于执行了Animal a = new Cat(),这时a和c同时指向Cat对象,但此时a不能访问Cat类扩展的数据成员,所以再将a强转成Cat类型即可。如果不存在这样的转型机制,则针对猫和狗我们还要分别写两个函数f(Cat c)和f(Dog d)。但其实上图程序的可扩展性也不是最好的。我们还可以利用动态绑定(即多态)将扩展性进一步提升。多态机制的三个前提分别是:
(1)要有继承
(2)要重写,即子类对父类中某些方法进行重新定义
(3)要向上转型,用父类引用指向子类对象。
下面来看一个例子:
class Animal { private String name; /**
* 在Animal类自定义的构造方法
* @param name */
Animal(String name) { this.name = name;
} /**
* 在Animal类里面自定义一个方法enjoy */
public void enjoy() {
System.out.println("动物的叫声……");
}
}class Cat extends Animal { private String eyesColor; /**
* 在子类Cat里面定义Cat类的构造方法
* @param n
* @param c */
Cat(String n, String c) { /**
* 在构造方法的实现里面首先使用super调用父类Animal的构造方法Animal(String name)。
* 把子类对象里面的父类对象先造出来。 */
super(n);
eyesColor = c;
} /**
* 子类Cat对从父类Animal继承下来的enjoy方法不满意,在这里重写了enjoy方法。 */
public void enjoy() {
System.out.println("我养的猫高兴地叫了一声……");
}
}/**
* 子类Dog从父类Animal继承下来,Dog类拥有了Animal类所有的属性和方法。
* @author gacl
* */class Dog extends Animal { /**
* 在子类Dog里面定义自己的私有成员变量 */
private String furColor; /**
* 在子类Dog里面定义Dog类的构造方法
* @param n
* @param c */
Dog(String n, String c) { /**
* 在构造方法的实现里面首先使用super调用父类Animal的构造方法Animal(String name)。
* 把子类对象里面的父类对象先造出来。 */
super(n);
furColor = c;
} /**
* 子类Dog对从父类Animal继承下来的enjoy方法不满意,在这里重写了enjoy方法。 */
public void enjoy() {
System.out.println("我养的狗高兴地叫了一声……");
}
}/**
* 子类Bird从父类Animal继承下来,Bird类拥有Animal类所有的属性和方法
* @author gacl
* */class Bird extends Animal { /**
* 在子类Bird里面定义Bird类的构造方法 */
Bird() { /**
* 在构造方法的实现里面首先使用super调用父类Animal的构造方法Animal(String name)。
* 把子类对象里面的父类对象先造出来。 */
super("bird");
} /**
* 子类Bird对从父类Animal继承下来的enjoy方法不满意,在这里重写了enjoy方法。 */
public void enjoy() {
System.out.println("我养的鸟高兴地叫了一声……");
}
}/**
* 定义一个类Lady(女士)
* @author gacl
* */class Lady { /**
* 定义Lady类的私有成员变量name和pet */
private String name; private Animal pet; /**
* 在Lady类里面定义自己的构造方 * ady(),
* 这个构造方法有两个参数,分别为String类型的name和Animal类型的pet,
* 这里的第二个参数设置成Animal类型可以给我们的程序带来最大的灵活性,
* 因为作为养宠物来说,可以养猫,养狗,养鸟,只要是你喜欢的都可以养,
* 因此把它设置为父类对象的引用最为灵活。
* 因为这个Animal类型的参数是父类对象的引用类型,因此当我们传参数的时候,
* 可以把这个父类的子类对象传过去,即传Dog、Cat和Bird等都可以。
* @param name
* @param pet */
Lady(String name, Animal pet) { this.name = name; this.pet = pet;
} /**
* 在Lady类里面自定义一个方法myPetEnjoy()
* 方法体内是让Lady对象养的宠物自己调用自己的enjoy()方法发出自己的叫声。 */
public void myPetEnjoy() {
pet.enjoy();
}
}public class Jerque { public static void main(String args[]) { /**
* 在堆内存里面new了一只蓝猫对象出来,这个蓝猫对象里面包含有一个父类对象Animal。 */
Cat c = new Cat("Catname", "blue"); /**
* 在堆内存里面new了一只黑狗对象出来,这个黑狗对象里面包含有一个父类对象Animal。 */
Dog d = new Dog("Dogname", "black"); /**
* 在堆内存里面new了一只小鸟对象出来,这个小鸟对象里面包含有一个父类对象Animal。 */
Bird b = new Bird(); /**
* 在堆内存里面new出来3个小姑娘,名字分别是l1,l2,l3。
* l1养了一只宠物是c(Cat),l2养了一只宠物是d(Dog),l3养了一只宠物是b(Bird)。
* 注意:调用Lady类的构造方法时,传递过来的c,d,b是当成Animal来传递的,
* 因此使用c,d,b这三个引用对象只能访问父类Animal里面的enjoy()方法。 */
Lady l1 = new Lady("l1", c);
Lady l2 = new Lady("l2", d);
Lady l3 = new Lady("l3", b); /**
* 这三个小姑娘都调用myPetEnjoy()方法使自己养的宠物高兴地叫起来。 */
l1.myPetEnjoy();
l2.myPetEnjoy();
l3.myPetEnjoy();
}
}
上面的例子中,我们发现,如果我们想要加入新的动物,只需定义相应的类继承Animal,完全不用动任何一处代码,因为这里运用了面向对象最核心的东西——多态。与之前的例子不同,虽然我们一直强调当用父类的引用指向子类对象,父类无法访问子类自己的成员,但是方法与数据成员不同,具体调哪一个方法是等到运行时决定的,new出了什么对象就调用相应对象的方法,取决于实际new出的对象而不是指向对象的引用,所以当传入不同动物类型,mypetEnjoy()就会去执行不同的方法
0
投稿
猜你喜欢
- 1.引言在操作应用的时候,会有很多不同的手势操作,如按下、单击、双击、长按等手势,我们可以在这些手势事件中添加相应的业务逻辑,那么如何检测不
- public class CrossSum{ public static void main(String args[]){
- 本文实例为大家分享了C#超市收银系统设计的具体代码,供大家参考,具体内容如下1.登录界面代码如下:using System;using Sy
- 文件上传在web应用中非常普遍,要在jsp环境中实现文件上传功能是非常容易的,因为网上有许多用java开发的文件上传组件,本文以common
- 一、安装Maven下载地址:https://maven.apache.org/download.cgi把下载的安装包解压tar -xvf a
- 当我们在做前后端分离的开发时,在使用fetch交换数据的时候,提示Access-Control-Allow-Origin跨域问题,解决方案跟
- Android 集成FlutterFlutter 作为 Google 开源的新一代跨平台、高性能 UI 框架,旨在帮助开发者高效地构建出跨平
- 装箱是将值类型转换为 object 类型或由此值类型实现的任何接口类型的一个过程。 当 CLR 对值类型进行装箱时,会将该值包装到 Syst
- 本文实例讲述了java获取百度网盘真实下载链接的方法。分享给大家供大家参考。具体如下:目前还存在一个问题,同一ip在获取3次以后会出现验证码
- 本文实例为大家分享了Android实现类似微信视频接听的具体代码,供大家参考,具体内容如下1、背景需求:业务需要接入视频审核功能,在PC 端
- mybatis-plus 查询传入参数Map,返回List<Map>原因有时实体类属性不够用,又不想写自定义VO了,所以用map
- 为了实现不同环境构建的不同需求,这里使用到了 profile。因为 profile 能够在构建时修改 pom 的一个子集,或者添加额外的配置
- HttpResponse 讲解HttpServletResponse概述:在创建Servlet时会覆盖service()方法,或doGet(
- 有时候,我们需要将控件的背景颜色设定为透明,比如说label(标签)控件。那么,如何将控件的背景颜色设定为透明?是不是只要将控件的BackC
- 开发一款App,总会遇到各种各样的需求和业务,这时候选择一个简单好用的轮子,就可以事半功倍前言 Intent intent =
- spring.activemq.pool.enabled=false时,每发送一条数据都需要创建一个连接,这样会出现频繁创建和销毁连接的场景
- 用java实现循环队列的方法:1、添加一个属性size用来记录眼下的元素个数。目的是当head=rear的时候。通过size=0还是size
- 这篇文章主要介绍了spring boot多数据源动态切换代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值
- 1.基本语法key: value;kv之间有空格大小写敏感使用缩进表示层级关系缩进不允许使用tab,只允许空格缩进的空格数不重要,只要相同层
- 在最近写的一个天气APP中用到了圆形头像这样的一个样式,中间是圆形的头像(被圆形切割的图片),周围是一个带颜色的圆环。如下图所示,今天就来说