JAVA中关于多态的理解

先了解两个概念:向上转型向下转型

 

向上转型

父类引用指向子类对象

这样做的意义是:

当我们需要多个同父的对象调用某个方法时,通过向上转换后,则可以确定参数的统一.方便程序设计。

向上转型的缺陷

animal a = new cat();
a.catchMouse();

 a引用了子类猫的对象,编译器比较笨,它只会根据引用的类型去寻找字节码文件,于是它到animal.class中寻找catchMouse(抓老鼠这个方法),没有找到所以就报错了

向下转型

父类转型成子类就是向下转型

 

注意事项

无论是向上转型还是向下转型,都必须要求转型的两个类是有继承关系的。

例如


public class Demo {
    public static void main(String[] args) {
        animal a = new cat();
        bird b = (bird)a;
        b.catchMouse();
    }

}
class animal{
    public void speak(){
        System.out.println("动物在叫");
    }
}
class bird extends animal{
    @Override
    public void speak() {
        System.out.println("鸟儿在叫");
    }
}
class cat extends animal{
    public void speak(){
        System.out.println("猫在叫");
    }
    public void catchMouse(){
        System.out.println("抓老鼠");
    }
}

cat类和bird类都继承于animal类,但是cat类与bird类没有继承关系所以,上述代码会抛出异常

向下转型是用来解决向上转换的缺陷的。所以当我们想调用子类的特有方法时,为了使编译器不报错,需要让编译器去找子类的字节码,这样编译才能通过。

但是!!!! 编译通过了,运行阶段不一定通过!例如上面的b是一个cat类型的引用变量,但是a实际上是一个bird对象,而bird对象中没有catchMouse(),所以就会引发ClassCastException异常。

所以,使用向下转型的前提条件必须保证转型的两个类必须有继承关系(等号左边的引用和等号右边引用所指向的对象必须有继承关系)

如何避免ClassCastException异常

但是,有时候类多了,可能不好理清类与类之间的关系,JAVA提供了一个关键字instanceof来判断引用所指向的对象的类型

关于instancof有以下几点

  • instanceof可以在运行阶段动态判断引用所指向的对象的类型
  • instanceof的语法是 (引用 instanceof 类型)
  • instanceof运算符的返回结果只能是:true/false

实际应用例子

public class Demo {
    public static void main(String[] args) {
        animal a = new cat();
        if(a instanceof cat){
            cat b = (cat)a;
            b.catchMouse();
        }

    }

}

如果a引用指向的对象是一个cat类的对象,那么则进行向下转型

多态

首先看一个例子

鸟类和猫类继承于动物类,鸟和猫类中重写了动物类中的speak方法

当用一个cat类的引用变量 c去引用一个cat对象时,c.speak()方法输出的是 "猫在叫",那么我们用animal 类的引用变量C 去引用一个cat对象时,C.speak()方法输出的又是什么呢?

 

答案还是 "猫在叫",为什么呢?这就要引出多态的概念了


public class Demo {
    public static void main(String[] args) {
        //猫再叫
        cat c = new cat();
        c.speak();

        //鸟在叫
        bird b = new bird();
        b.speak();

        animal C = new cat();

        animal B = new bird();
        C.speak();
        B.speak();
    }

}
class animal{
    public void speak(){
        System.out.println("动物在叫");
    }
}
class bird extends animal{
    @Override
    public void speak() {
        System.out.println("鸟儿在叫");
    }
}
class cat extends animal{
    public void speak(){
        System.out.println("猫在叫");
    }
}

什么是多态

父类型引用指向子类型对象。包括编译阶段和运行阶段。

编译阶段:绑定父类的方法。

运行阶段:动态绑定子类型对象的方法

如何实现多态

分析C.speak();

java程序分为编译和运行阶段

编译阶段:对于编译器来说,编译器知道C的类型是animal,所以会在语法检查时去找animal.class中的speak()方法,找到了,绑定上speak()方法,编译通过,静态绑定成功。(编译阶段属于静态绑定)

运行阶段:运行阶段,实际上在堆内存中创建的对象时cat对象,所以speak()的时候,真正参与speak的对象是一只猫,所以运行阶段会动态执行cat对象的speak()方法。这个过程属于运行阶段绑定。(运行阶段绑定属于动态绑定)

多态表示多种形态:编译时候一种形态,运行时候另一种形态。

 

多态在开发中的作用

OCP

在软件开发中,有一条原则是OCP(开闭原则),即对扩展开放,对修改关闭。

意思是在软件的扩展过程中,修改的越少越好。

作用

降低程序的耦合度,提高程序的扩展力

使用多态,意味着我们可以使用父类的引用来指向子类的对象,可以在父类里设定一个方法,参数为父类的引用,每次传进子类的对象,再利用方法重写,去实现子类的相关功能。这样我们在扩展程序时候只需要加子类,而不需要修改父类,减少了对程序的修改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值