对JAVA多态的理解

对JAVA基础多态的理解

多态是JAVA中面对对象的一种体现,它也提高了一段代码的复用性和扩展性。
所谓的多态,用一句话来说:相同的行为,不同的实现
多态又分为两种:静态多态动态多态

静态多态

这里的静态是与static无关,那什么叫静态多态?
它是指:某个方法在编译期就确定了运行期调用的是哪个实现。
比如:
单独的方法重写
在继承关系中,子类拥有和父类相同的行为,但是允许子类重新实现。换句话说就是父类有父类的实现,子类有子类的实现。

方法的重载
当一个类中,拥有多个相同的行为(方法名相同),但是参数类型不同,各自有各自的实现

这个两种方法都体现了静态多态,它们都在编译期就确定了运行期要调用的事哪个实现。

动态多态

java的精髓之一

它是指:某个方法只有在运行期才知道调用的是哪个实现。
它是通过动态绑定和重写实现
在继承中,父类的引用可以在运行时交给各个子类的对象,那么我们要调用这个对象的这个行为时是可以通过这个对象的父类的引用直接进行调用的。但是前提是这个行为父类要有。
而子类对这个行为有不同的实现时,我们就需要进行方法的重写,但是怎么让我们调用时确保调用的是子类的实现,而不是父类的实现呢?
这个时候,我们就要转型

转型

在父类中,子类自动继承父类的属性和行为,那么这个子类是不是就不属于父类了?答案肯定是属于的,就好比:田园犬、二哈、藏獒,你能说它们不是狗吗?
所以当子类new一个对象的时候,这个对象还是父类的这个类型中的,属于is-a关系;它只是父类这个类型当中的某一个类型的对象。
那么这个子类对象一定是父类对象之一
我们都知道基本类型转换分为自动转换强制转换
自动转换: 取值范围小的数据类型转换为取值范围大的数据类型,可以直接进行转换,语法也不需要更改,这种转换没有任何风险
强制转换: 取值范围大的数据类型转换为取值范围小的数据类型,这种我们就需要在语法上 进行更改;比如:double转int,语法:int变量名 = (int)double变量名
这种转换会造成精度丢失
应用数据类型转换
应用数据类型转换有一个前提条件------只有继承关系的类才能进行转换,兄第类都不可以!!!
应用数据类型分为向上转型和向下转型
向上转型 (自动转型)
它是子类转换为父类,就是把范围小的对象直接放到范围大的引用变量中,这个时候我们可以直接转,是没有风险的。
在内存上看:因为每个子类对象都包含了一个完整的父类对象,只是这个父类的引用指向这个对象时,它只能看到属于父类的属性和方法,或者说只能看到定义在父类的属性和方法。
向下转型(强制转型)
把父类(范围大)的对象直接放到子类(范围小)的引用变量中,
在内存上,父类是不可能包含一个完整的子类的,当子类指向这个对象时,会发现有一部分什么都没有,这种转换是有风险的------编译不会报错,但是运行期是可能会发生错误ClassCastExcepthion(类型转换)
要想不发生风险,最终的执行效果只能是本类的引用指向本类的对象

所以根本原则:
1、转型只发生在有继承关系的类
2、父类的引用指向子类的对象,自动转换,没有问题;子类的引用不能指向父类的对象,否则就有报错的风险。
3、强转后,最终效果一定是本类的对象指向。

instanceof 运算符

那么我们怎么知道这个类型的对象是不是我们本类的呢?
这时候我们需要用到instanceof 运算符
它是boolean类型运算符,返回“真”或“假”
它专门用来判断某个对象是否是某种类型的,语法:对象名 instanceof 类型

这个时候,我们怎么实现动态多态呢?
设计的关键点:1、父类的引用,可以在运行时交给它各种子类的对象(因为子类数据类型转父类数据类型 是直接转换)
2、调用的是定义在父类中,又被子类重写了的方法!开始定义在父类时为了保证,用父类的引用可以调用到这个方法。而让子类去重写,是为了体现不同子类的相同行为不同实现的动态多态性。

如果想要调用子类特有方法,那么我们就不能使用父类引用(因为它看不到子类的特有属性、行为)
在这种情况下,我们只能把引用换成相应的子类引用(记住:换的是引用,不是对象)

由于父类引用可以指向任何子类,所以当我们拥有父类引用的时候就不敢保证强转的正确性,所以我们在做应用数据类型强转之前,一定要做 instanceof 判断是否属于这个类型。

以上本人粗鄙之见!!!

你可能感兴趣的:(java基础)