栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java多态

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java多态

   多态性 Java引用变量有两个类型:一个是编译时类型,一个是运行时类型。编译时类型由声明该变量 时使用的类型决定,运行时类型由实际 赋给该变量的对象决定。如果编译时类型和运行时类型不 一致,就可 能出现所谓的多态(Polymorphism)。 先看下面程序。   上面程序的main()方法中显式创建了三个引用变量,对于前两个引用变量bc和sc,它们编译时类 型和运行时类型完全相同,因此调用 它们的成员变量和方法非常正常,完全没有任何问题。但第 三个引用 变量ploymophicBc则比较特殊,它的编译时类型是baseClass,而运行 时类型是 SubClass,当调用该引用变量的test()方法(baseClass类中 定义了该方法,子类SubClass覆盖了 父类的该方法)时,实际执行的 是SubClass类中覆盖后的test()方法,这就可能出现多态了。         因为子类其实是一种特殊的父类,因此Java允许把一个子类对象 直接赋给一个父类引用变量, 无须任何类型转换,或者被称为向上转 型(upcasting),向上转型由系统自动完成。                 当把一个子类对象直接赋给父类引用变量时,例如上面的 baseClass ploymophicBc=newSubClass();,这个ploymophicBc引用 变量的编译时类型是 baseClass,而运行时类型是SubClass,当运行时 调用该引用变量的方法时,其方法行为总是表 现出子类方法的行为特 征,而不是父类方法的行为特征,这就可能出现:相同类型的变量、 调用 同一个方法时呈现出多种不同的行为特征,这就是多态。         上面的main()方法中注释了ploymophicBc.sub();,这行代码会在编译时引发错误。虽然 ploymophicBc引用变量实际上确实包含sub()方 法(例如,可以通过反射来执行该方法),但因为 它的编译时类型为 baseClass,因此编译时无法调用sub()方法。         与方法不同的是,对象的实例变量则不具备多态性。比如上面的ploymophicBc引用变量,程序 中输出它的book实例变量时,并不是输 出SubClass类里定义的实例变量,而是输出baseClass类 的实例变量。
注意: 引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所 具有的方法。因此,编写Java代码 时,引用变量只能调用声明该变量时所用类里包含的方 法。 例如, 通过Object p=new Person()代码定义一个变量p,则这个p只能调用 Object类的方 法,而不能调用Person类里定义的方法。 注意: 通过引用变量来访问其包含的实例变量时,系统总是试图访问 它编译时类型所定义的 成员变量,而不是它运行时类型所定义的成 员变量。
 引用变量的强制类型转换        编写Java程序时,引用变量只能调用它编译时类型的方法,而不能调用它运行时类型的方法, 即使它实际所引用的对象确实包含该方 法。如果需要让这个引用变量调用它运行时类型的方法, 则必须把它 强制类型转换成运行时类型,强制类型转换需要借助于类型转换运算 符。         类 型 转 换 运 算 符 是 小 括 号 , 类 型 转 换 运 算 符 的 用 法 是 :(type)variable,这种用 法可以将variable变量转换成一个type类型 的变量。前面在介绍基本类型的强制类型转换时,已经 看到了使用这 种类型转换运算符的用法,类型转换运算符可以将一个基本类型变量 转换成另一个 类型。
除此之外,这个类型转换运算符还可以将一个引用类型变量转换成其子类类型。这种强制类 型转换不是万能的,当进行强制类型转换 时需要注意: ➢ 基本类型之间的转换只能在数值类型之间进行,这里所说的数 值类型包括整数型、字符型和浮点型。但数值类型和布尔类型 之间不能进行类型转换。 ➢ 引用类型之间的转换只能在具有继承关系的两个类型之间进 行,如果是两个没有任何继承关系的类型,则无法进行类型转 换,否则编译时就会出现错误。如果试图把一个父类实例转换 成子类类型,则这个对象必须实际上是子类实例才行(即编译 时类型为父类类型,而运行时类型是子类类型),否则将在运 行时引发ClassCastException异常。

 

下面是进行强制类型转换的示范程序。下面程序详细说明了哪些情况可以进行类型转换,哪些情况 不可以进行类型转换。

 

  考虑到进行强制类型转换时可能出现异常,因此进行类型转换之前应先通过instanceof运算符来判 断是否可以成功转换。例如,上面 的var str=(String)objPri;代码运行时会引发 ClassCastException 异常,这是因为objPri不可转换成String类型。为了让程序更加健 壮,可以将 代码改为如下: 在进行强制类型转换之前,先用instanceof运算符判断是否可以成功转换,从而避免出现 ClassCastException异常,这样可以保证程 序更加健壮。
注意: 当 把 子 类 对 象 赋 给 父 类 引 用 变 量 时 , 被 称 为 向 上 转 型(upcasting),这种转型 总是可以成功的,这也从另一个侧面证实 了子类是一种特殊的父类。这种转型只是表明这个 引用变量的编译 时类型是父类,但实际执行它的方法时,依然表现出子类对象的行 为方式。 但把一个父类对象赋给子类引用变量时,就需要进行强制 类型转换,而且还可能在运行时产 生ClassCastException异常,使 用instanceof运算符可以让强制类型转换更安全。
instanceof和类型转换运算符一样,都是Java提供的运算符,与+、-等算术运算符的用法大致相 似,下面具体介绍该运算符的用法。

 

 

instanceof运算符的前一个操作数通常是一个引用类型变量,后一个操作数通常是一个类(也可以 是接口,可以把接口理解成一种特 殊的类),它用于判断前面的对象是否是后面的类,或者其子 类、实 现类的实例。如果是,则返回true,否则返回false。 在使用instanceof运算符时需要注 意:instanceof运算符前面操 作数的编译时类型要么与后面的类相同,要么与后面的类具有父子 承 关系,否则会引起编译错误。下面程序示范了instanceof运算符的 用法。

 

上面程序通过Object hello="Hello";代码定义了一个hello变量,这个变量的编译时类型是Object 类,但实际类型是String。因为 Object类是所有类、接口的父类,因此可以执行hello instanceof String和hello instanceof Math等。 但如果使用var a="Hello";代码定义的变量a,就不能执行a instanceof Math,因为编译器会推断出a 的编译类型是String, String类型既不是Math类型,也不是Math类型的父类,所以这行代码 编译就 会出错 instanceof运算符的作用是:在进行强制类型转换之前,首先判断前一个对象是否是后一个类的实 例,是否可以成功转换,从而保证 代码更加健壮。 instanceof和(type)是Java提供的两个相关的运 算符,通常先用 instanceof判断一个对象是否可以强制类型转换,然后再使用(type) 运算符进行强 制类型转换,从而保证程序不会出现错误
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/322990.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号