Java多态

什么是多态?

多态是面向对象程序设计的一个重要特征,指同一个实体同时具有多种形式,即同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。

以一段简单的代码来说明Java中的多态:

public class Animal {
    public void run(){
        System.out.println("父类Animal的run方法");
    }
}
class Cat extends Animal{
    public void run(){
        System.out.println("子类Cat的run方法");
    }
}
class Test{
    public static void main(String[] args) {
     Animal  a2= new Cat();
     a2.run();
    }
}
结果:子类Cat的run方法

分析a2.run();

Java程序分为编译阶段和运行阶段。

先分析编译阶段:

        对于编译器来说,编译器只知道a2的类型是Animal,

        所以编译器在检查语法的时候,会去Animal.class字节码文件中找run()方法,

        找到了,绑定run()方法,编译通过,静态绑定成功。(编译阶段属于静态绑定)

运行时阶段:

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

从上面可以看出:其实多态就是表示多种形态,编译时候一种形态,运行时时另一种形态。

其实多态包括编译时多态和运行时多态两个阶段:

1,编译时多态:

方法的重载

编译时多态:方法的重载

方法重载就是在同一个类中,出现了多个同名的方法,他们的参数列表(方法签名)不同

根据实际参数的数据类型、个数和次序,Java在编译时能够确定执行重载方法中的哪一个。

方法重写时的编译时多态:

除了重载,重写也表现出两种多态性。当一个对象的引用指向的是当前对象所属类的对象时,为编译时多态,其他则为运行时多态。

意思就是方法名相同通过参数列表的不同(多种状态)来确定使用的方法。

2,运行时多态:

运行时多态: 当父类引用指向子类对象时:

父类只能执行那些在父类中声明、被子类覆盖了的子类方法,而不能执行子类新增加的成员方法。在编译时期,首先会去查看父类里面有没有这个方法,如果没有的话向上继续查找,直到找到Object类如果还没有的话就报错,如果有的话,到运行阶段,再去看一下子类中有没有覆盖该方法,如果覆盖了,则执行子类覆盖的方法。如果没有则执行父类中原本的方法。

1,当子类和父类有相同属性时,父类还是会执行自己所拥有的属性,若父类中没有的属性子类中有,当父类对象指向子类引用时(向上转型),在编译时期就会报错

2,对于static方法还是会执行父类中的方法,这是由于在运行时,虚拟机已经认定static方法属于哪个类。“重写”只能适用于实例方法,不能用于静态方法。对于静态方法,只能隐藏,重载,继承。子类会将父类静态方法的隐藏(hide),但子类的静态方法完全体现不了多态,就像子类属性隐藏父类属性一样,在利用引用访问对象的属性或静态方法时,是引用类型决定了实际上访问的是哪个属性,而非当前引用实际代表的是哪个类。因此,子类静态方法不能覆盖父类的静态方法

总结:多态是指不同子类型的对象对同一行为作出不同的响应。 多态性分为编译时的多态性和运行时的多态性。方法重载实现的是编译时的多态性,而方法重写实现的是运行时的多态性。 对于运行时多态,特别注意,父类引用指向子类对象,在调用实例方法时,调用的是子类重写之后的,并且不能调用子类新增的方法,对于属性和static方法来说,还是执行父类原有的。

为什么要使用多态?

11,多态的好处/缺点

1.不使用多态时:

好处:可以调用子类的特有行为

弊端:扩展性极差

2.使用多态时:(可替换,可扩充,接口性,灵活,简化性)

好处:扩展性强,让代码更灵活,提高代码的复用性

弊端:不能调用子类对象的特有行为(方法)

在使用多态时,要调用子类对象特有方法是,我们可以向下转型,这时,为了避免强转出现问题,我们应该使用instanceof关键字来判断关键字左边的变量是否为右边的类型,返回boolean类型的结果即可。

通过以下可以看出代码的灵活性,改变的代码更少(不需要再重新写方法的调用,只需要改变右边的对象)

public class Animal {
    public void run(){
        System.out.println("父类Animal在跑");
    }
}
class Cat extends Animal{
    public void run(){
        System.out.println("子类Cat在跑");
    }
}
class Dog extends Animal{
    public void run(){
        System.out.println("子类Dog在跑");
    }
}
class Test{
    public static void main(String[] args) {
       // Animal animal = new Cat();
        Animal animal= new Dog();//只需要改变右边对象
        animal.run();//不需要改变了
    }
}

实现多态的三个必要条件:

1,继承

2,重写(没有重写的话无法完成运行时多态,执行的依旧是父类的方法)

3,父类引用指向子类对象

向上转型,向下转型

向上转型:

当有子类对象赋值给一个父类引用时,便是向上转型,多态本身就是向上转型的过程

使用格式:

父类类型 变量名 = new 子类类型();

向下转型:

一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用转为子类引用,这个过程是向下转型。如果是直接创建父类对象,是无法向下转型的。

使用格式:

子类类型 变量名 = (子类类型) 父类类型的变量;

向下转型的代码示例:

public class Animal {
    public void run(){
        System.out.println("父类Animal的run方法");
    }
    public void move(){
        System.out.println("父类Animal的move方法");
    }
}
class Cat extends Animal{
    public void run(){
        System.out.println("子类Cat的run方法");
    }
}
class Test{
    public static void main(String[] args) {
        Animal animal = new Cat();
        Cat cat=(Cat)animal;//向下转型
        cat.move();//子类调用父类的方法
        cat.run();
        animal.run();
    }
}
结果:父类Animal的move方法
    子类Cat的run方法
    子类Cat的run方法

instanceOf

它是 Java 的保留关键字。它的作用是在运行阶段判断它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。

严格来说,instanceof 是 Java 的一个二元操作符(双目运算符),类似于 ==,>,< 等操作符。用来测试一个对象是否是为一个类的实例,用法为:

boolean result = obj instanceof class

其中 obj 为一个对象,Class 表示一个类或者一个接口。

当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回 true,否则返回false。 注意:编译器会检查 obj 是否能转换成右边的class类型,如果不能转换则直接报错,如果不能确定类型,则通过编译,具体看运行时定

代码示例:

注意:只有两个类有继承关系才能使用instanceof要不然会编译错误。

Java规范当中规定,对类型进行向下转型的时候,一定要使用instanceof运算符来进行判断。(避免ClassCastException,类型转换异常)

public class Animal {
}
class Cat extends Animal{

}
class Dog extends Animal{
}
class Test{
    public static void main(String[] args) {
        Animal animal = new Cat();
        Animal animal01= new Dog();
        if(animal01 instanceof Cat){
            System.out.println("animal01是一只Cat");
        }else {
            System.out.println("animal01不是一只Cat");
        }
    }
}

结果:animal01不是一只Cat

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值