Java:多态

简介: Java多态的介绍

继承是为了复用父类代码,同时继承也为实现多态做了铺垫。

Java的引用变量有两个类型:编译时类型和运行时类型。
编译时类型:由声明该变量时使用的类型决定;运行时类型:由实际赋值给该变量的对象决定。
如果编译时类型和运行时类型不一致,会出现所谓的多态。

public class Father {
    public void func1() {
        System.out.println("父类的func1方法!");
        func2();
    }
    
    public void func2() {
        System.out.println("父类的func2方法!");
    } }
public class Son extends Father {    //子类会继承父类的func1,func2方法
    //子类func1方法重载
    public void func1(String s) {
        System.out.println("子类的func1方法!");
        func2();
    }
    
    //子类func2方法重写
    public void func2() {
        System.out.println("子类的func2方法!");
    } }

子类的对象赋值给父类类型的引用变量称为向上强制类型转换(子类的向上转型)。

public class Test {
    public static void main(String[] args) {
        Father f = new Son(); //向上强制类型转换
        
        f.func1();
    } }

结果显示为:f.func1();  调用了 父类的func1()方法 和 子类的func2()方法。
image.png

 分析:Father f = new Son(), 出现多态,而且子类重载了func1(),即func1(String s),而父类中没有含参数的方法,所以向上转型后会掉失子类的该方法;重写了func2(),那指向Son的Father引用会优先调用Son的func2()方法,即同名称且同参数的方法中,优先调用运行时类型的类。

总结:
指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用这些方法优先使用子类定义的其方法。

注:单单访问属性的值时会调用编译类型的属性;若在函数中调用或访问属性时,会调用该类自身的属性。在JAVA中,函数调用绑定采用的是动态绑定方式,对象的属性是在声明时指定,方法是对象的执行行为。

多态实现机制:

基于继承(包括接口,对接口的实现也可以理解为一种特殊的继承)的多态实现机制主要表现在父类和继承该父类的一个或多个子类对某些方法的重写,多个子类对同一个方法的重写可以表现出不同的形态。

创建一个类就是创建一个新的数据类型,而类在java中属于引用数据类型。

public class A {
    public String show(A a) {
        return "A AND A";
    }
    
    public String show(D d) { //数据类型D
        return "A AND D";
    } }
public class B extends A {
    public String show(B b) {
        return "B AND B";
    }
    
    public String show(A a) {
        return "B AND A";
    } }
public class C extends B { }
public class D extends B { }
public class Test {
    public static void main(String[] args) {
             A A1 = new A(); //A类型创建A的对象,不存在多态,调用的方法局限于A类中
            A A2 = new B(); //编译时类型和运行时类型不一致,存在多态,调用的方法需要考虑与父类共有,但子类优先。
            B B = new B(); //存在继承,拥有部分父类的属性和方法
            C C = new C();
            D D = new D();
            
            System.out.println("1--" + A1.show(B)); //B是A的子类,多态,准许子类型对象赋给父类类型的引用变量,所以 B对应传给参数a
            System.out.println("2--" + A1.show(C));
            System.out.println("3--" + A1.show(D)); //直接调用

            System.out.println("4--" + A2.show(B)); //父类不存在参数B的方法,无法调用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));
    } }

image.png

在继承链中对象方法的调用存在优先级:
this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。
基类,父类,超类是指被继承的类;派生类,子类是指继承于基类的类。

首先我们分析5,A2.show(C),A2是A类型的引用变量,所以this就代表了A,A2.show(C),它在A类中找发现没有找到,于是到A的超类中找(super),由于A没有超类(Object除外),所以跳到第三级,也就是this.show((super)O),C的超类有B、A,所以(super)O为B、A,this同样是A,这里在A中找到了show(A a),同时由于A2是B类的一个引用且B类重写了show(A a),因此最终会调用子类B类的show(A a)方法,结果也就是B and A。

当超类对象引用变量引用子类对象时,被引用对象的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,在看一个例子说明:A2.show(B);

这里A2是引用变量,为A类型,它引用的是B对象,因此按照上面那句话的意思是说由B来决定调用谁的方法,所以A2.show(B)应该要调用B中的show(B b),产生的结果应该是“B and B”,但是为什么会与前面的运行结果产生差异呢?这里我们忽略了后面那句话“但是这儿被调用的方法必须是在超类中定义过的”,那么show(B b)在A类中存在吗?根本就不存在!所以这句话在这里不适用?那么难道是这句话错误了?不是!其实这句话还隐含这这句话:它仍然要按照继承链中调用方法的优先级来确认。所以它才会在A类中找到show(A a),同时由于B重写了该方法所以才会调用B类中的方法,否则就会调用A类中的方法。

目录
相关文章
|
4月前
|
算法 Java 程序员
在Java的编程世界里,多态不仅仅是一种代码层面的技术,它是思想的碰撞,是程序员对现实世界复杂性的抽象映射,是对软件设计哲学的深刻领悟。
在Java的编程世界里,多态不仅仅是一种代码层面的技术,它是思想的碰撞,是程序员对现实世界复杂性的抽象映射,是对软件设计哲学的深刻领悟。
73 9
|
4月前
|
Java 开发者
在Java面向对象编程的广阔海洋中,多态犹如一股深邃的潜流,它推动着代码从单一走向多元,从僵化迈向灵活。
在Java面向对象编程的广阔海洋中,多态犹如一股深邃的潜流,它推动着代码从单一走向多元,从僵化迈向灵活。
43 7
|
4月前
|
Java 开发者
那些年,我们一同踏入Java编程的大门,多态,这个充满魔法的名字,曾无数次点亮我们探索面向对象编程的热情。
那些年,我们一同踏入Java编程的大门,多态,这个充满魔法的名字,曾无数次点亮我们探索面向对象编程的热情。
49 5
|
4月前
|
Java 程序员
让我们一起探讨Java多态的奥秘,看看它是如何打破“一刀切”的局限,让我们的代码更加生动多彩
让我们一起探讨Java多态的奥秘,看看它是如何打破“一刀切”的局限,让我们的代码更加生动多彩
43 5
|
4月前
|
Java 程序员
Java中的继承和多态:理解面向对象编程的核心概念
【8月更文挑战第22天】在Java的世界中,继承和多态不仅仅是编程技巧,它们是构建可维护、可扩展软件架构的基石。通过本文,我们将深入探讨这两个概念,并揭示它们如何共同作用于面向对象编程(OOP)的实践之中。你将了解继承如何简化代码重用,以及多态如何为程序提供灵活性和扩展性。让我们启程,探索Java语言中这些强大特性的秘密。
|
2月前
|
存储 Java 测试技术
Java零基础-多态详解
【10月更文挑战第10天】Java零基础教学篇,手把手实践教学!
32 4
|
2月前
|
Java 编译器 程序员
Java多态背后的秘密:动态绑定如何工作?
本文介绍了Java中多态的实现原理,通过动态绑定和虚拟方法表,使得父类引用可以调用子类的方法,增强了代码的灵活性和可维护性。文中通过具体示例详细解析了多态的工作机制。
60 4
|
3月前
|
Java 编译器
封装,继承,多态【Java面向对象知识回顾①】
本文回顾了Java面向对象编程的三大特性:封装、继承和多态。封装通过将数据和方法结合在类中并隐藏实现细节来保护对象状态,继承允许新类扩展现有类的功能,而多态则允许对象在不同情况下表现出不同的行为,这些特性共同提高了代码的复用性、扩展性和灵活性。
封装,继承,多态【Java面向对象知识回顾①】
|
2月前
|
Java
java继承和多态详解
java继承和多态详解
50 5
|
2月前
|
存储 Java 测试技术
Java零基础-多态详解
【10月更文挑战第1天】Java零基础教学篇,手把手实践教学!
29 1