多态、向上转型和向下转型

本文详细介绍了Java中的向上转型(子类到父类)和向下转型(父类到子类),强调了转型时的注意事项,如需访问子类特有方法时需使用向下转型,并通过`instanceof`运算符进行类型判断以避免异常。同时,解释了多态性的概念,即父类型引用指向子类型对象,探讨了编译阶段和运行阶段的绑定机制。此外,还通过实例展示了如何在代码中正确使用这些概念。
摘要由CSDN通过智能技术生成
  1. 向上转型(upcasting)和向下转型(downcasting)

    • 向上转型:

      • 子类——>父类,即自动类型转换

    • 向下转型:

      • 父类——>子类,即强制类型转换【需要加强制类型转换符】

      • 需要访问/调用子类对象中”特有“的方法,才用向下转型

    • 两类型之间必须要有继承关系,没有继承关系编译无法通过

  2. 何为多态

    • 多态指的是:父类型引用指向子类型对象,包括编译阶段和运行阶段

    • 编译阶段绑定父类方法,运行阶段绑定子类型对象的方法

  3. instanceof运算符

    • java.lang.ClassCastException:类型转换

    • java.lang.NullPionterExpception:空指针异常

    • instanceof可以在运行阶段动态判断引用指向的对象的类型

    • instanceof的语法:【引用instanceof类型】

    • instanceof运算符的结果只能是:true/false

    • c是一个引用,c变量保存了内存地址指向了堆中的对象,例子看下面代码的行

    • 无论何时何地,对类型进行向下转型时,要使用instanceof运算符进行判断,好避免ClassCastException\

package com.two.mebb;
​
public class Animal01 {//父类
    public void move() {
        System.out.println("动物在移动");
    }
}
​
package com.two.meaa;
​
import com.two.mebb.Animal01;
​
public class Cat01 extends Animal01 {//子类
    public void move() {
        System.out.println("猫在移动");
    }
​
    //猫自己特有的行为,即子类型特有的方法
    public void eat() {
        System.out.println("猫吃老鼠");
    }
}
package com.two.meaa;
​
import com.two.mebb.Animal01;
​
public class Bird01 extends Animal01 {//子类
        public void move() {
            System.out.println("鸟在飞翔");
        }
    }
package com.two.me;
​
import com.two.meaa.Bird01;
import com.two.meaa.Cat01;
import com.two.mebb.Animal01;
​
public class DuoTest01 {
    public static void main(String[] args) {
        Animal01 a1 = new Animal01();
        a1.move();//动物在移动
​
        Cat01 c1 = new Cat01();
        c1.move();//猫在移动
​
        Bird01 b1 = new Bird01();
        b1.move();//鸟在飞翔
​
        //换种写法
        Animal01 a2 = new Cat01();
        /*父类型的引用允许指向子类型的对象
        a2就是父类型的引用
        new Cat01()是一个子类型的对象
        */
        a2.move();//猫在移动
        /*什么是多态?分析a2.move();
        * java程序分为编译阶段和运行阶段,
        * 对编译阶段:
        * 对编译器来说,编译器只知道a2的类型是Animal
        * 所以编译器在检查语法时,会去Animal。class字节码文件中找move方法
        * 找到了就绑定上move()方法,编译通过,静态绑定成功(编译阶段属于静态绑定)
        * 再是运行阶段:
        * 此时,实际上的堆内存中创建的java对象是Cat对象,所以move的时候
        * 真正参与move的对象是一只猫
        * 所以运行阶段会动态执行Cat对象的move()方法
        * 此过程称为动态绑定
        * */
        Animal01 a3 = new Cat01();
        Cat01 x = (Cat01)a3;//进行强转
        x.eat();
        /*a3.eat();不行,why?
        * 因为编译器只知道a3是Animal01类型
        * 去Animal01.class文件找eat()方法找不到
        * 静态绑定失败,编译报错,无法运行
        * 只有编译通过的代码才能运行,编译不通过,就轮不到运行
        * */
​
        /*Animal01 a4 = new Bird01();
        * Bird01 y = (Bird01)a4;
        * y.eat();
        * 编译器检测到的a4这个引用是Animal01类型
        * 而Animal01与Cat之间存在继承关系,所以可以向下转型,编译没问题,
        * 运行阶段,堆内存实际创建的对象是Bird01对象,
        *
        *c是一个引用,c变量保存了内存地址指向了堆中的对象
        *假设(c instanceof Cat)为true表示:c引用指向的堆内存中的java对象是一个Cat
        *假设(C instanceof Cat)为false表示:c引用指向的堆内存中的java对象不是一个Cat
        *
        * */
        Animal01 a4 = new Bird01();
        System.out.println(a4 instanceof Cat01);//false
        if(a4 instanceof Cat01){//如果a4是一只Cat
            Cat01 y = (Cat01)a4;//再进行强制类型转换
            y.eat();
        }
        /*疑问:肉眼可以看到底层到底是new Bird01()还是new Cat01(),
        * 为什么还要进行instanceof的判断?
        * 因为,以后可能肉眼看不到
        * */
​
​
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值