一、多态的基本概念
Java中的多态性是面向对象中的第三大主要特征(其余两个是封装和继承)。多态性实际上是在继承的基础上扩展出来的。
二、方法的多态性主要体现在以下两个方面
- 方法的重载(Overload)
这种现象主要发生在同一个类中,对于两个或多个方法,他们拥有相同的方法名,但是方法的参数类型或者数目不同,则称为发生了方法的重载。方法的重载与方法的返回类型无关。也就是说如果两个方法仅返回值类型不同,则不称为方法的重载。
public void fun(){
System.out.println("方法调用");
}
//重载上一个方法
public String fun(String value){
return "方法调用";
}
- 方法的复写(Override)
这种现象主要发生在父、子类中,子类中的某个方法复写了父类中的某个方法以实现不同的功能。这两个方法拥有相同的方法名,相同的参数类型以及相同的参数个数。同样的如果原方法仅仅与重写的方法返回值类型不同,也不称为方法的复写。
//父类
public class Father {
public void fun(){
System.out.println("方法调用");
}
}
//子类
public class Son extends Father {
@Override
public void fun() {
System.out.println("方法的复写");
}
}
三、对象的多态性
主要体现在父、子类实例之间的转换处理。父、子实例的相互转换有两种模式一种是向上转型,一种是向下转型。
- 对象的向上转型
这种转型是自动的,也是我们日常编程中最常使用的。它实际上就是将一个子类对象赋值给父类引用。
public static void main(String[] args) {
//对象的向上转型
Father f=new Son();
}
用途:这种转型的主要用于参数的统一化设计,便于日后的方法维护。请看下面的代码。
//父类
public class Msg {
public void printMsg(){
System.out.println("父类打印的消息");
}
}
//子类1
public class NetMsg extends Msg{
@Override
public void printMsg(){
System.out.println("子类网络连接信息");
}
}
//子类2
public class DataMsg extends Msg{
@Override
public void printMsg(){
System.out.println("子类数据库连接信息");
}
}
--------------------------------------------------
public class demo {
//定义一个方法,参数为Msg类型
public static void demo_fun(Msg msg){
msg.printMsg();
}
//调用方法
public static void main(String[] args) {
//调用子类1
demo_fun(new NetMsg());
//调用子类2
demo_fun(new DataMsg());
}
--------------------------------------------------
输出:子类网络连接信息
子类数据库连接信息
- 对象的向下转型(需要强制类型转换)
首先要说明的是这种转型是存在风险的,在日常的使用中,需要我们先将子类对象向上转型,然后再向下转型,进而才能使用子类中特有的方法。注意:这个对象实质上是一个子类对象。
看例子:
//父类
public class Person {
public void dailyWork(){
System.out.println("吃饭、睡觉、写代码");
}
}
//子类
public class SuperMan extends Person {
public void specialWork(){
System.out.println("拯救世界");
}
}
--------------------------------------------------
public static void main(String[] args) {
//向上转型
Person p = new SuperMan();
//向下转型
((SuperMan) p).specialWork();
}
--------------------------------------------------
输出:拯救世界
需要注意的一点是我们无法将一个父类对象赋值给一个子类引用!
如果我们未经强制类型转换就是用子类中特有的方法,那么将无法通过编译,这也就是上面说的风险所在。看代码:
public static void main(String[] args) {
Person p=new SuperMan();
//无法通过编译,找不到这个方法
p.specialWork();
}