Java学习:十三.方法覆盖和多态---多态

一.向上转型和向下转型

在这里插入图片描述

其实,无论是向上转型还是向下转型,两个类型之间必须有继承关系。
注意:
向上转型:自动类型转换
向下转型:强制类型转换,需要强制类型转换符

二.举例分析

public class Animal {
    
    
    public void move() {
    
    
    	System.out.println("动物在移动");
    }
}
public class Cat extends Animal{
    
    
    public void move() {
    
    
    	System.out.println("猫儿在走猫步");
    }
}

public class Bird extends Animal{
    
    
    public void move() {
    
    
    	System.out.println("鸟儿在飞翔");
    }
}

public class Test01 {
    
    
	public static void main(String[] args) {
    
    
		 Animal a1 = new Animal();
		    a1.move();
		    
		    Cat b1 = new Cat();
		    b1.move();
		    
		    Bird c1 = new Bird();
		    c1.move();
		    
		    Animal a2 = new Cat();
		    Animal a3 = new Bird();
		    
		    a2.move();
		    a3.move();
	}
}

在这里插入图片描述

大家注意看一下这两行代码:

        Animal a2 = new Cat();
	    Animal a3 = new Bird();

在编译阶段,编译器只知道a2的类型是Animal,所以编译器在检查语法时,会去Animal.class字节码文件中寻找move方法,找到,绑定上move(),属于静态绑定。

在运行阶段,实际对象是堆中创建的对象Cat对象,所以在运行阶段会动态地去执行Cat对象的move方法。动态绑定。
(我们这里只分析了第一行代码,第二行类似)

这就是我们所说的多态,编译和运行不一样。
我们再总结一下多态是指:

  • 父类型引用指向子类型对象
  • 编译阶段:绑定父类型的方法
  • 运行阶段:绑定子类型对象的方法

接下来我们改一下程序:

改一下cat类

public class Cat extends Animal{
    
    
    public void move() {
    
    
    	System.out.println("猫儿在走猫步");
    }
    public void catchMouse() {
    
    
    	System.out.println("猫儿在抓老鼠");
    }
}


改一下主类

public class Test01 {
    
    
	public static void main(String[] args) {
    
    
		 Animal a1 = new Animal();
		    a1.move();
		    
		    Cat b1 = new Cat();
		    b1.move();
		    
		    Bird c1 = new Bird();
		    c1.move();
		    
		    Animal a2 = new Cat();
		    Animal a3 = new Bird();
		    
		    a2.move();
		    a3.move();
		    
		    Animal a5 = new Cat();
		    a5.catchMouse();
	}
}

我们使用cmd进行编译,但不运行,结果编译不通过
在这里插入图片描述
我们通过结果发现,编译的时候因为Animal.class无法找到catchMouse(),所以编译不通过。
所以我们要使用类型转换。

三.向下转型

什么时候必须使用向下转型呢?
—》当我们要使用子类中特有的方法时
我们按照这个思路,改一下主类:

public class Test01 {
    
    
	public static void main(String[] args) {
    
    
		 Animal a1 = new Animal();
		    a1.move();
		    
		    Cat b1 = new Cat();
		    b1.move();
		    
		    Bird c1 = new Bird();
		    c1.move();
		    
		    Animal a2 = new Cat();
		    Animal a3 = new Bird();
		    
		    a2.move();
		    a3.move();
		    
		    Animal a5 = new Cat();
		    //a5.catchMouse();
		    
		    Cat x = (Cat)a5;
		    x.catchMouse();
	}
}

我们强制转换了a5
结果正确。
在这里插入图片描述

四.instanceof判断

向下转型虽然解决了我们的问题,但是向下转型还是有风险的,我们在主类中加三行如下代码:

Animal a6 = new Bird();
		    Cat y = (Cat)a6;
		    y.catchMouse();

主类:

public class Test01 {
    
    
	public static void main(String[] args) {
    
    
		 Animal a1 = new Animal();
		    a1.move();
		    
		    Cat b1 = new Cat();
		    b1.move();
		    
		    Bird c1 = new Bird();
		    c1.move();
		    
		    Animal a2 = new Cat();
		    Animal a3 = new Bird();
		    
		    a2.move();
		    a3.move();
		    
		    Animal a5 = new Cat();
		    //a5.catchMouse();
		    
		    Cat x = (Cat)a5;
		    x.catchMouse();
		    
		    Animal a6 = new Bird();
		    Cat y = (Cat)a6;
		    y.catchMouse();
	}
}

在这里插入图片描述
编译通过了,但运行没有通过。原因是运行阶段,实际对象Bird不能转换成Cat,它们之间没有继承关系,当然也就是鸟不可能抓老鼠,所以我们引进了instanceof判断避免这个异常。
大家要格外记住这个异常:java.lang.ClassCastException 类型转换异常

instanceof:(1)可以在运行阶段动态判断引用指向对象类型
(2)语法:(引用 instanceof 类型)
(3)instanceof的结果只能是true或者false
(4)c是一个引用,c中保存的内存地址指向堆内存中的对象。
假设(c instanceof Cat)为true表示c引用指向的堆内存中的java对象是一个Cat
假设(c instanceof Cat)为false表示c引用指向的堆内存中的java对象是一个Bird
我们加了判断条件后,代码如下:

public class Test01 {
    
    
	public static void main(String[] args) {
    
    
		 Animal a1 = new Animal();
		    a1.move();
		    
		    Cat b1 = new Cat();
		    b1.move();
		    
		    Bird c1 = new Bird();
		    c1.move();
		    
		    Animal a2 = new Cat();
		    Animal a3 = new Bird();
		    
		    a2.move();
		    a3.move();
		    
		    Animal a5 = new Cat();
		    //a5.catchMouse();
		    
		    Cat x = (Cat)a5;
		    x.catchMouse();
		    
		    Animal a6 = new Bird();
		    if(a6 instanceof Cat)
		    {
    
    
		    	Cat y = (Cat)a6;
		    	y.catchMouse();
		    }
	}
}

在这里插入图片描述
运行结果正确。

最近笔者也在运营公众号,欢迎大家的关注!我们一起学习Java,一起进步。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45965358/article/details/113839258