这是一篇关于如何正确理解Java转型机制的文章

这是一篇关于如何正确理解Java转型机制的文章

谨以此文纪念明天要默单词我还在复习Java谁让他明天考Java呢

什么是转型

就是转型啊还能怎么说!子类转父类,父类转子类巴拉巴拉。父类转子类需要注意

这里边有什么不好理解呢,主要有这几点:

  • 假如说子类重写了父类的一个函数,那么不管子类转父类或者父类转子类,转完了之后调用该函数,那么执行的是父类的函数还是子类的呢?
  • 到底谁可以转成谁?还是说可以随意互相转?(当然不是)
  • 强制类型转换是什么?

本文将以如下两个类进行讲解,第一个是父类Person,只有一个方法WhatAreYou:

class People
{
    public People() {
        // TODO Auto-generated constructor stub
        System.out.println("Father");
    }
    public void WhatAreYou()
    {
        System.out.println("我是一个人类");
    }
}

第一个子类,男人,继承了父类People的WhatAreYou,同时有自己独特的方法Hunt:

class Men extends People
{
    public Men() {
        // TODO Auto-generated constructor stub
        System.out.println("Men");
    }


    public void Hunt() {    
        //男人独有的打猎技能
        System.out.println("Men hunting");
    }

    public void WhatAreYou()
    {
        System.out.println("I am A Man");
    }
}

第二个子类,女人,继承了父类People的WhatAreYou,同时有自己独特的方法Breed(哺育小孩):

class Women extends People
{
    public Women() {
        // TODO Auto-generated constructor stub
        System.out.println("Women");
    }

    public void WhatAreYou()
    {
        System.out.println("I am a Woman");
    }

    public void Breed()
    {   
        //女人才能哺育小孩
        System.out.println("Women Breeding child");
    }
}

子类转父类

先来看一段代码:

public static void main(String[] args)
    {
        People people = new Men();
        people.WhatAreYou();
        people = new Women();
        people.WhatAreYou();
    }

输出结果是:

这里写图片描述

第一行输出Father是父类构造函数,都是先执行父类构造函数后执行子类构造,可以显示调用父类构造函数(关键字Super) 第二行是子类Men的构造函数的输出。

高潮来了:

people是People型引用,但是给他一个Men的对象后,调用其WhatAreYou函数就是调用了子类的函数。

下一行的给people赋值Women也是一样道理。

父类转子类

这能行么…看下边这个代码(只截图了)

这里写图片描述

把父类转到子类直接报错

来看看编译器给出的解决方案:

  • 第一种是把Men men = new People()改为Men men = (Men)new People()

    来看看这样改会怎么样:

    这里写图片描述

    哦编译确实是不报错,但是运行阶段抛出异常

    也就是说,父类不能转换为子类.

    但是这也是有例外的,如果父类引用本就是由子类转化而来,那么他可以转为子类。看如下一段代码:

public static void main(String[] args)
    {
        People people = new Men();
        Men men = (Men)people;
        men.WhatAreYou();
    }

这段代码很皮地将子类转为父类,由转回子类。那么会不会报错呢?看运行:

这里写图片描述

完美运行。

这里其实涉及到能不能强制转换的问题。比如一个Integer对象,就不能转换为一个string对象,谁让他不是string的子类呢?

java提供了用于判断能不能完成强制转型的关键字:instanceof,用法如下:

if ( A instanceof ClassB )
{ ClassB b = (ClassB)A ;}

总结

经过试验,得出结论:子类无压力转父类,父类转子类有条件,那就是该父类对象本就是由子类转的。

或许是这样:

子类转父类实际上是用一个父类型的引用指向子类型的对象,而父类型的引用这个东西,是专门为了服务父类的对象而产生的,可以说其中放了一个表,表项一个是父类中的变量和函数,另一个就是其指向的实体对象中相应的变量和函数。由于子类是父类的扩展,所以子类中一定有父类中有的变量和函数,所以该父类引用的表可以填满,正常使用;而反过来说,子类型的引用的表中有一些是父类所没有的,表项无法填满,故而出错。而父类转子类的那个特殊情况,可能是JVM给对象打了一个tag。

大体如下图所示:

这是向上转型:

这里写图片描述

父类转子类:

这里写图片描述

实体对象中有函数没有被表项指向无所谓,大不了不用这个函数;(实际也就是这么干的)

但是如果表项中有项目没有目标是不行的,表项中的东西是登记了给人用的,项目没有目标用个锤子?

引用中存放表项的方法是我为了简化理解想出来的,实际可能与此不用,建议读者查阅介绍JVM的书籍自行理解

!!!!!有一句话要记住,函数表是根据引用的类型调用的,但是实际运行的是实体对象的函数体

标了!!!!!的那句话极其重要

标了!!!!!的那句话极其重要

或者皮一点,儿子都想当老子,你让他当老子他屁颠屁颠就去了;(向上转型)

老子不想当儿子,除非他原来就是儿子,破格当了一会儿老子,现在要把他变回儿子,就要强制转成儿子(向下转型,只能强制转换,而且有条件)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值