详细讲述Java中的对象转型

 更新时间:2018年10月15日 15:46:40   投稿:laozhang  
在本篇文章里我们给大家详细分享了关于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类里面定义自己的构造方法Lady(),
  * 这个构造方法有两个参数,分别为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()就会去执行不同的方法

相关文章

  • java实现mp3合并的方法

    java实现mp3合并的方法

    这篇文章主要介绍了java实现mp3合并的方法,是Java操作多媒体文件的一个典型应用,非常具有参考借鉴价值,需要的朋友可以参考下
    2014-10-10
  • 一文弄懂Java中ThreadPoolExecutor

    一文弄懂Java中ThreadPoolExecutor

    ThreadPoolExecutor是Java中的一个线程池实现,它可以管理和控制多个 Worker Threads,本文就详细的介绍一下Java中ThreadPoolExecutor,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • java 查找替换pdf中的指定文本

    java 查找替换pdf中的指定文本

    这篇文章主要介绍了java 如何查找替换pdf中的指定文本,帮助大家更好的理解和使用Java,感兴趣的朋友可以了解下
    2020-12-12
  • RocketMQ NameServer架构设计启动流程

    RocketMQ NameServer架构设计启动流程

    这篇文章主要为大家介绍了RocketMQ NameServer架构设计启动流程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • hadoop实现grep示例分享

    hadoop实现grep示例分享

    这篇文章主要介绍了hadoop实现grep示例,可从文档中提取包含某些字符串的行,需要的朋友可以参考下
    2014-03-03
  • Java多线程中常见的几个问题

    Java多线程中常见的几个问题

    这篇文章主要介绍了Java多线程中常见的几个问题 ,需要的朋友可以参考下
    2015-05-05
  • Spring Batch实现批量处理

    Spring Batch实现批量处理

    本文主要介绍了Spring Batch进行批量处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • JAVA实现空间索引编码——GeoHash的示例

    JAVA实现空间索引编码——GeoHash的示例

    本篇文章主要介绍了JAVA实现空间索引编码——GeoHash的示例,如何从众多的位置信息中查找到离自己最近的位置,有兴趣的朋友可以了解一下
    2016-10-10
  • Spring事件监听详解

    Spring事件监听详解

    这篇文章主要介绍了Spring事件监听详解,文中有非常详细的图文解说及代码示例,对正在学习java Spring的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-05-05
  • java 矩阵乘法的mapreduce程序实现

    java 矩阵乘法的mapreduce程序实现

    这篇文章主要介绍了java 矩阵乘法的mapreduce程序实现的相关资料,需要的朋友可以参考下
    2017-06-06

最新评论