Java多态

什么是多态?

多态(Polymorphism)是面向对象编程(OOP)中的一个核心概念,它允许同一个接口或方法在不同对象上具有不同的实现方式。Java作为一种面向对象的编程语言,广泛地利用了多态特性来提高代码的灵活性和可扩展性。

多态使同一个行为具有多个不同表现形式或形态的能力。

即,同一个接口,使用不同的实例而执行不同操作,Java的多态性就是对象多种表现形式的体现。

就比如:

现实中,比如我们按下 F1 键这个动作:

  • 如果当前在 Word 下弹出的就是 Word 帮助;
  • 在 Windows 下弹出的就是 Windows 帮助和支持。

同一个事件发生在不同的对象上会产生不同的结果。

多态存在的三个必要条件

  • 继承:必须有继承关系的的父子类
  • 重写:子类对于父类的某些方法进行了重写
  • 父类引用指向子类对象,如:Parent p = new Child();(Parent父类引用指向了子类Child对象)

多态需要进行重写操作,我们来回顾一下什么是Java的重写,并对比一下重写和重载的区别;

重载:

  1. 方法名称相同;
  2. 参数列表不同(数据类型, 顺序, 参数的个数);
  3. 返回值不做要求.

重写(发生在父类与子类当中)

  1. 方法名称相同;
  2. 返回值相同(返回值构成父类子关系也可以);
  3. 参数列表相同(数据类型, 参数个数, 顺序).

区别点

重写(override)

重载(override)

参数列表

一定不能修改

必须修改

返回类型

一定不能修改(除非可以构成父子类关系)

可以修改

访问限定符

一定不能做更严格的限制(可以降低限制)

可以修改

同时,上面提到了父类引用指向子类对象,这个时候我们需要了解到一个概念:

向上转型:

子类引用的对象转换为父类类型称为向上转型。通俗地说就是是将子类对象转为父类对象。此处父类对象可以是接口。

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

使用格式:

父类类型  对象名  = new 子类类型();

与向上转型相对的,还有一个概念为向下转型

向下转型

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

使用格式:

子类类型 子类对象名 = (子类类型) 父类对象名

下面我们来看一个经典案例来更好地理解多态的概念;

class A {
    public String show(D obj) {
        return ("A and D");
    }
 
    public String show(A obj) {
        return ("A and A");
    }
 
}
 
class B extends A{
    public String show(B obj){
        return ("B and B");
    }
 
    public String show(A obj){
        return ("B and A");
    }
}
 
class C extends B{
 
}
 
class D extends B{
 
}
 
public class Demo {
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new B();
        B b = new B();
        C c = new C();
        D d = new D();
 
        System.out.println("1--" + a1.show(b));
        System.out.println("2--" + a1.show(c));
        System.out.println("3--" + a1.show(d));

        System.out.println("4--" + a2.show(b));
        System.out.println("5--" + a2.show(c));
        System.out.println("6--" + a2.show(d));

        System.out.println("7--" + b.show(b));
        System.out.println("8--" + b.show(c));
        System.out.println("9--" + b.show(d));
    }
}
//输出结果:
//1--A and A
//2--A and A
//3--A and D

//4--B and A
//5--B and A
//6--A and D

//7--B and B
//8--B and B
//9--A and D
 

前三个我们来画一下内存图来分析一下:

对于前三个来讲,我们创建了A类型的a1对象,它里面两个show方法,我们调用a1.show(b)

这时候虽然A b发生了向上转型,但是,我们调用的a1里的方法还是那两个,新向上转型的b指向的和a1所指向的对象是不同的,同样第二个第三个结果 c和d都继承于b ,b又继承与a,所以也是向上转型成了A类型,但是a1指向仍是不变(他没有子类对象,没有发生重写)

那么第四个为什么不是B and B呢?

这里就要学点新东西了。

当父类对象引用变量引用子类对象时,被引用对象的类型决定了调用谁的成员方法,引用变量类型决定可调用的方法。如果子类中没有覆盖该方法,那么会去父类中寻找。

也就是说,我们向上转型的a2对象,他的子类重写了A类的show(A)方法,因此,只能访问到重写后的方法。

了解完这个例子,我们可以总结一下多态向上转型后的特点;

 多态的特点
  1. 多态情况下,子类和父类存在同名的成员变量时,访问的时父类的成员变量
  2. 多态情况下,子父类存在同名的非静态成员方法时,访问的是子类中重写的方法
  3. 多态情况下,子父类存在同名的静态成员变量成员方法时,访问的是父类的成员函数
  4. 多态情况下,不能访问子类独有的方法

对于第二点,就可以很好的解释了上面例子当中第四条输出的结果了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值