多态性JAVA,java多态理解

  多态性JAVA,java多态理解

  

目录

Java基础知识(多态)多态的定义和存在的必要条件多态的定义:多态存在的三个必要条件多态的案例多态的好处引用类型转换1。什么是引用类型转换,为什么需要它?2.向上转换(自动转换)3。向下转化(强制转化)4。向下转化的问题。变形6的异常。在千千有成千上万的人。谢谢你看到这里。希望我的能对你的有所帮助!互相鼓励!

 

  愿你以后继续爱下去,去山海!

  

Java基础知识(多态)

 

  00-1010由于具体的类是在程序运行时确定的,这样,引用变量就可以在不修改源代码的情况下绑定到各种类实现上,导致引用调用的具体方法发生变化,即不修改程序代码就可以改变程序绑定的具体代码,使程序可以选择多种运行状态。这就是多态性。

  

多态

 

  00-1010多态性是指同一行为具有多种不同表现或形式的能力。多态是同一个接口,使用不同的实例执行不同的操作。以动物为例。猫和狗属于动物的范畴,而动物有一个共同的吃的行为,不同的动物吃的食物也不同。

  猫,它喜欢吃鱼!

  至于狗,它们更喜欢啃骨头!

  因此,多态性意味着对于吃的行为,每种动物在这种行为中的表现都是不同的。

  

多态的定义和存在的必要条件

继承或实现多态性中必须有具有继承或实现关系的子类和超类。

 

  方法的被覆盖子类重定义(覆盖)了父类中的一些方法,当这些方法被调用时,子类的方法也会被调用。

  基类引用指向派生类对象,即父类引用指向子类对象的父类类型:它引用子类对象继承的父类类型或实现的父接口类型。

  多态的格式:

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

  变量名。方法名();

  多态格式可以充分体现同一个接口,使用不同的实例来执行不同的操作。

  接下来我们来一个具体的案例体验吧!

  00-1010多态性我们首先需要知道:

  在多态模式下调用方法时,首先检查方法是否存在于父类中,如果不存在,则编译错误;如果是,则执行子类化后的方法。如果子类没有覆盖这个方法,它将调用父类的这个方法。

  总结一下,编译时向左看,运行时向右看。

  首先,我们来定义一个母兽。动物有进食行为!

  然后定义一只猫和一只狗来继承动物,重写里面的进食行为!

  具体代码如下:

  定义动物父类:

  包com . NZ . POJO;/* * *定义一个父类first-animal类*动物都有一个吃的行为属性*/public类animal { public void eat(){ system . out . println(动物都吃!);}}定义cat子类:

  包com . NZ . POJO;/* * *定义猫继承自动物,*重写里面的进食行为,因为猫也有进食行为,但是猫喜欢吃罐头*/public类cat扩展了animal { public void eat(){ system . out . println(小喵喵喜欢吃鱼罐头!);}}定义puppy子类:

  包com . NZ . POJO;/* * *定义狗继承动物,*重写里面的吃的行为,因为狗也有吃的行为,但是狗喜欢啃骨头*/public class dog扩展animal { public void eat(){ system . out . println(小狗爱啃骨头!);}}定义测试类并测试多态的形式:

  包com . NZ;import com . NZ . POJO . animal;导入com . NZ . POJO . cat;导入com . NZ . POJO . dog;/* * *测试多态形式*/public class demo { public static void main(string[]args){//多态形式,创建cat类对象Animal Animal=new Cat();

   // 调用的是Cat的 eat animal.eat(); // 多态形式,创建狗类对象 Animal animal2 = new Dog(); // 调用的是Dog的eat animal2.eat(); }}得到的结果:

  

小喵咪都喜欢吃鱼罐头!小狗狗都爱啃骨头!

 

  

类的大致结构:

 

  

 

  可以看出我们可以使用多态的属性得到不同的动物的一个吃的行为属性!

  

 

  

多态的好处

提高了代码的拓展性,使用父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用。

 

  具体我们来看看吧:

  继续使用上述的动物类、猫类、狗类吧。

  定义测试类:

  

package com.nz;import com.nz.pojo.Animal;import com.nz.pojo.Cat;import com.nz.pojo.Dog;/** * 测试多态的好处 */public class Demo2 { public static void main(String[] args) { // 创建猫和狗对象 Cat cat = new Cat(); Dog dog = new Dog(); // 调用catEat catEat(cat); // 调用dogEat dogEat(dog);/* 多态的好处: 以上各个动物的吃的方法, 我们都可以使用animalEat(Animal a)方法来代替。 并且执行效果都一样, 所以我们可以使用animalEat直接替代了不同动物的吃方法。 */ animalEat(cat); animalEat(dog); } /* 定义几个不同吃的方法,看看具体调用后的结果是什么吧! */ public static void catEat (Cat cat){ cat.eat(); } public static void dogEat (Dog dog){ dog.eat(); } public static void animalEat (Animal animal){ animal.eat(); }}

执行结果:

 

  

小喵咪都喜欢吃鱼罐头!小狗狗都爱啃骨头!小喵咪都喜欢吃鱼罐头!小狗狗都爱啃骨头!

 

  

可以看出,由于多态的特性,我们的animalEat()方法传入的Animal类型参数,并且它是我们的Cat和Dog的父类类型,父类类型接收子类对象,所以我们可以将Cat对象和Dog对象,传递给animalEat()方法。

 

  所以我们可以完全使用animalEat()方法来替代catEat()方法和dogEat()方法,达到同样的效果!以至于我们可以不必再单独写xxxEat()方法来传入指定的动物参数了,从而实现了实现类的自动切换。

  所以多态的好处体现在:可以使我们的程序编写的更简单,并有良好的扩展性。

  

 

  

多态的弊端

从上面的多态的好处,可以看到我们可以使用父类的参数代替了某个子类的参数,从而达到程序的扩展!

 

  但是对于某个子类有些独有的功能方法时,此时我们的多态的写法就无法访问子类独有功能了。

  具体来瞧瞧?

  代码如下:

  重新定义下猫的子类:

  

package com.nz.pojo;/** * 定义猫类继承动物类, * 随之重写里面的吃行为,因为猫也有吃的行为,但是猫喜欢吃罐头 */public class Cat extends Animal{ public void eat() { System.out.println("小喵咪都喜欢吃鱼罐头!"); } /** * 增加一哥猫咪特有的玩球方法() */ public void playBall() { System.out.println("小喵咪都喜欢小球!"); }}

定义测试类:

 

  

package com.nz;import com.nz.pojo.Animal;import com.nz.pojo.Cat;/** * 测试多态的弊端! */public class Demo3 { public static void main(String[] args) { Animal animal = new Cat(); animal.eat(); animal.playBall();//编译报错,编译看左边,Animal没有这个方法 }}

可以看到动物类和猫类有个共同的eat吃方法,但是呢,猫咪多了个玩球球的方法。而对于动物对象来说,它本身动物类没有玩球球的方法,所以它的编译就直接没有通过了!

 

  那有什么方法解决呢?且看下一章节吧!

  

 

  

引用类型转换

 

  

1. 引用类型转换是什么,为什么需要它?

从上面的多态的弊端的案例中,我们可以看到,我们使用动物对象时无法直接访问到猫类中的玩球球方法,这也就是我们之前说的编译看左边,运行看右边。

 

  而在我们使用多态方式调用方法时,首先检查会左边的父类中是否有该方法,如果没有,则编译错误。也就代表着,父类无法调用子类独有的方法。、

  所以说,如果编译都错误,更别说运行了。这也是多态给我们带来的一点小困扰,而我们如果想要调用子类特有的方法,必须做向下转型。

  

 

  

2. 向上转型(自动转换)

对于向下转型,我们先来讲解下向上转型的概念吧。

 

  向上转型:

  

 

  多态本身是子类向父类向上转换(自动转换)的过程,这个过程是默认的。当父类引用指向一个子类对象时,便是向上转型。

  对于父类和子类的关系来说,具体来看图说话:

  

 

  父类相对与子类来说是大范围的类型,Animal是动物类,是父类。而Cat是猫咪类,是子类。

  所以对于父类Animal来说,它的范围是比较大的,它包含一切动物,包括猫咪类和小狗类。

  所以对于子类类型这种范围小的,我们可以直接自动转型给父类类型的变量。

  使用格式:

  

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

 

  如:Animal animal = new Cat();

  相当于有:Animal animal = (Animal) new Cat();

  

相当于自动帮我们了一个隐形的转换为动物类的一个过程,因为动物本身就包含了猫咪。

 

  

 

  

3. 向下转型(强制转换)

向上转型可以知道它是子类自动转换为父类的一个过程,所以我们现在再来看看向下转型的定义:

 

  向下转型:

  

 

  向下转型就是由父类向子类向下转换的过程,这个过程是强制的。一个需要将父类对象转为子类对象,可以使用强制类型转换的格式,这便是向下转型。

  为什么这种就必须自己强制加上一个类型转换过程呢?

  对于父类和子类的关系来说,我们接着看图说话:

  

 

  对于猫咪类的话,它在动物类中只是其中的一部分吧,而对于动物类来说,它有许多其他子类动物如狗,牛,猪等等。

  所以对于动物父类想要向下转型的时候, 它此时不知道指向那个子类,因为不确定呀,所以就必须自己加上强制的类型转换的一个过程。

  使用格式:

  

子类类型 变量名 = (子类类型) 父类变量名;如:Animal animal = new Cat();Cat cat = (Cat) animal;cat.playBall();// 此时我们就可以使用猫咪的特有方法啦

 

  

所以对于多态的弊端,无法使用子类特有的参数,我们也解决啦,可以通过向下转型的方法,从而将类型强制转换为某个子类对象后,再去调用子类的特有方法!

 

  

 

  

4. 向下转型的问题

虽然我们可以使用向下转型使得我们可以使用子类的独有方法,但是转型的过程中,一不小心就会遇到这样的问题了,来,我们来看看下面的代码:

 

  

public class Test { public static void main(String[] args) { // 向上转型 Animal a = new Cat(); a.eat(); // 调用的是 Cat 的 eat // 向下转型 Dog d = (Dog)a; d.watchHouse(); // 调用的是 Dog 的 watchHouse 【运行报错】 } }

这段代码可以通过编译,但是运行时,却报出了 ClassCastException ,类型转换异常!这是因为,明明创建了Cat类型对象,运行时,当然不能转换成Dog对象的。

 

  

 

  

5. 转型的异常

转型的过程中,一不小心就会遇到这样的问题,请看如下代码:

 

  定义狗类中额外的独有遛狗方法:

  

package com.nz.pojo;/** * 定义狗类继承动物类, * 随之重写里面的吃行为,因为狗也有吃的行为,但是狗喜欢啃骨头 */public class Dog extends Animal{ public void eat() { System.out.println("小狗狗都爱啃骨头!"); } public void walk() { System.out.println("小狗在被我溜着!"); }}

定义测试类

 

  

package com.nz;import com.nz.pojo.Animal;import com.nz.pojo.Cat;import com.nz.pojo.Dog;/** * 测试多态的向下转型的问题 */public class Demo4 { public static void main(String[] args) { // 向上转型的过程 Animal animal = new Cat(); // 调用了猫咪的吃方法 animal.eat(); // 向下转型 Dog dog = (Dog) animal; dog.walk(); // 调用的是 Dog 的 walk 可以通过,但是会运行报错 }}

得到结果:

 

  

小喵咪都喜欢吃鱼罐头!Exception in thread "main" java.lang.ClassCastException: com.nz.pojo.Cat cannot be cast to com.nz.pojo.Dogat com.nz.Demo4.main(Demo4.java:20)

 

  

我们可以看到,虽然我们的代码通过编译,但是终究在运行时,还是出错了,抛出了 ClassCastException 类型转换的异常。

 

  其实我们可以知道,我们在上面的时候,创建了Cat类型对象,而在向下转型时,将其强行转换为了Dog类型,所以程序在运行时,就会抛出类型转换的异常!

  那我们如何可以避免这种异常发生呢?且看下一节分析!

  

 

  

6. instanceof关键字

Java为我们提供一个关键字instanceof ,它可以帮助我们避免了ClassCastException 类型转换异常的发生。

 

  那如何做呢?

  格式:

  

变量名 instanceof 数据类型

 

  

解释:

 

  如果变量属于该数据类型或者其子类类型,返回true。如果变量不属于该数据类型或者其子类类型,返回false。代码实现:

  

package com.nz;import com.nz.pojo.Animal;import com.nz.pojo.Cat;import com.nz.pojo.Dog;/** * 使用instanceof解决类型转换异常! */public class Demo5 { public static void main(String[] args) { // 向上转型的过程 Animal animal = new Cat(); // 调用了猫咪的吃方法 animal.eat(); // 向下转型 if (animal instanceof Cat){ Cat cat = (Cat) animal; cat.playBall(); // 调用的是 Cat 的 playBall } else if (animal instanceof Dog){ Dog dog = (Dog) animal; dog.walk(); // 调用的是 Dog 的 walk } }}

结果:

 

  

小喵咪都喜欢吃鱼罐头!小喵咪都喜欢小球!

 

  

可以发现,它可以帮助我们在做类型转换前,判断该类型是否属于该类型或者子类类型,如果是,我们就可以强转啦!

 

  

 

  

总结

相信各位看官都对Java中的特性之一多态的知识和使用有了一定了解,等待下一次更多Java基础的学习吧!

 

  让我们也一起加油吧!本人不才,如有什么缺漏、错误的地方,也欢迎各位人才大佬评论中批评指正!

  

 

  学到这里,今天的世界打烊了,晚安!虽然这篇文章完结了,但是我还在,永不完结。我会努力保持写文章。来日方长,何惧车遥马慢!

  感谢各位看到这里!愿你韶华不负,青春无悔!

  到此这篇关于Java多态的全面系统解析的文章就介绍到这了,更多相关Java 多态内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: