值得理解的Java多态性

在网上想搜一下关于java多态的一些个人理解,最好是一些通俗易理解的,结果让不经意间看到了这篇文章,虽没有那么通俗易懂,但是通过下面的实例结合理解还是比较容易的。下面我就将这篇文章与大家分享一下:

本文带您通过几个类的示例和讲解来理解Java多态性,Java多态性的概念也可以被说成“一个接口,多个方法”。

(一)相关类:

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");
	}
	@Override
	public String show(A obj) {
		return ("B and A");
	}
}

class C extends B {
}

class D extends B {
}

 (二)问题:以下输出结果是什么?

 

public class Polymorphism {
	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(a1.show(b));   //①       
		System.out.println(a1.show(c));   //②      
		System.out.println(a1.show(d));   //③     
		System.out.println(a2.show(b));   //④   
		System.out.println(a2.show(c));   //⑤     
		System.out.println(a2.show(d));   //⑥      
		System.out.println(b.show(b));    //⑦    
		System.out.println(b.show(c));    //⑧ 
		System.out.println(b.show(d));    //⑨  
	}
}

 

(三)答案

①   A and A

②   A and A

③   A and D

④   B and A

⑤   B and A

⑥   A and D

⑦   B and B

⑧   B and B

⑨   A and D

 

(四)分析

     ①②③比较好理解,一般不会出错。④⑤就有点糊涂了,为什么输出的不是"B and B”呢?!!先来回顾一下多态性。

运行时多态性是面向对象程序设计代码重用的一个最强大机制,Java多态性的概念也可以被说成“一个接口,多个方法Java实现运行时多态性的基础是动态方法调度,它是一种在运行时而不是在编译期调用重载方法的机制。

 

      方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写(Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中Java多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。

 

      当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。 (但是如果强制把超类转换成子类的话,就可以调用子类中新添加而超类没有的方法了。)

 

      好了,先温习到这里,言归正传!实际上这里涉及方法调用的优先问题 ,优先级由高到低依次为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)让我们来看看它是怎么工作的。

比如④,a2.show(b),a2是一个引用变量,类型为A,则this为a2,b是B的一个实例,于是它到类A里面找show(B obj)方法,没有找到,于是到A的super(超类)找,而A没有超类,因此转到第三优先级this.show((super)O),this仍然是a2,这里O为B,(super)O即(super)B即A,因此它到类A里面找show(A obj)的方法,类A有这个方法,但是由于a2引用的是类B的一个对象,B覆盖了A的show(A obj)方法,因此最终锁定到类B的show(A obj),输出为"B and A”。

再比如⑧,b.show(c),b是一个引用变量,类型为B,则this为b,c是C的一个实例,于是它到类B找show(C obj)方法,没有找到,转而到B的超类A里面找,A里面也没有,因此也转到第三优先级this.show((super)O),this为b,O为C,(super)O即(super)C即B,因此它到B里面找show(B obj)方法,找到了,由于b引用的是类B的一个对象,因此直接锁定到类B的show(B obj),输出为"B and B”。

 

按照上面的方法,可以正确得到其他的结果。

 

问题还要继续,现在我们再来看上面的分析过程是怎么体现出蓝色字体那句话的内涵的。它说:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。还是拿a2.show(b)来说吧。

 

      a2是一个引用变量,类型为A,它引用的是B的一个对象,因此这句话的意思是由B来决定调用的是哪个方法。因此应该调用B的show(B obj)从而输出"B and B”才对。但是为什么跟前面的分析得到的结果不相符呢?!问题在于我们不要忽略了蓝色字体的后半部分,那里特别指明:这个被调用的方法必须是在超类中定义过的,也就是被子类覆盖的方法。B里面的show(B obj)在超类A中有定义吗?没有!那就更谈不上被覆盖了。实际上这句话隐藏了一条信息:它仍然是按照方法调用的优先级来确定的。它在类A中找到了show(A obj),如果子类B没有覆盖show(A obj)方法,那么它就调用A的show(A obj)(由于B继承A,虽然没有覆盖这个方法,但从超类A那里继承了这个方法,从某种意义上说,还是由B确定调用的方法,只是方法是在A中实现而已);现在子类B覆盖了show(A obj),因此它最终锁定到B的show(A obj)。这就是那句话的意义所在,到这里,我们可以清晰的理解Java的多态性了。

 

Java编程思想重点笔记(Java开发必看) Java学习必读经典,不管是初学者还是大牛都值得一读,这里总结书中的重点知识,这些知识不仅经常出现在各大知名公司的笔试面试过程中,而且在大型项目开发中也是常用的知识,既有简单的概念理解题(比如is-a关系和has-a关系的区别),也有深入的涉及RTTI和JVM底层反编译知识。 阅读详情

相关推荐

Java多态性与方法覆盖的深入探讨

本文深入解析了Java中的多态性概念以及方法覆盖(Overriding)的细节,强调了在运行时JVM如何根据对象的实际类型而非引用类型来调用相应的方法。文章还详细区分了方法覆盖和方法重载(Overloading)的不同点,并通过实际代码案例,阐释了多态性的实际应用以及如何在编程中正确使用方法覆盖和重载。

weixin_36212459的博客 292

Java多态性深入理解

经典代码 class A { public void show(D obj) { System.out.println("A and D"); } public void show(A obj) { System.out.println ("A and A"); } } class B extends A{ public voi

xingranzhihuo的博客 139

多态性与接口在面向对象编程中的应用

本文探讨了面向对象编程中的多态性原则,特别是通过接口实现多态的方法。文章解释了final方法和类的概念,以及如何在不相关的类之间共享方法和常量。通过案例研究,展示了如何创建和使用接口来处理多态性,以及如何实现接口和抽象类。文章强调了接口在标准化交互和扩展程序功能方面的重要性。

weixin_35391606的博客 385

Java 重写 多态性_java – 重载和重写方法中的多态性

我们来看看这个简单的Java代码:public class Animal {public void eat() {System.out.println("Generic Animal Eating Generically");}}public class Horse extends Animal {public void eat() {System.out.println("Horse eatin...

weixin_34652580的博客 179

Java中的接口与抽象类:深入理解与实践

接口定义行为规范,支持多态与多重继承;抽象类提供部分实现,利于代码复用与单一继承。Java 8的默认方法增强接口灵活性。抽象类含实例变量,接口限静态常量。设计模式中,接口适用策略、观察者等,抽象类适合模板方法、单例等,共筑软件灵活性与扩展性基石。

欢迎来到我的技术空间!我是一名经验丰富的Java开发工程师,热衷于分享我在软件开发领域的知识和心得。在这个博客里,您会发现一系列关于Java编程的文章,包括最佳实践、技术趋势、代码优化技巧以及一些有趣的项目案例。无论是初学者还是有经验的开发者,都能在这里找 1622

说一下你对多态的理解?_多态以及 LeetCode 每日一题

1 多态1.1 多态性Java 引用变量有两个类型:一个是编译时类型,一个是运行时类型。前者是代码中声明这个变量时的类型,后者是由实际对象的类型决定的。当编译类型和运行类型不一样时,产生多态。class 这个例子中 nc 的编译时类型是 BaseClass , 运行类型是 SubClass,在调用 nc 的方法时,总是显现除 SubClass 的行为特征。但是注意,实例变量不具有多态性。可以这么理...

weixin_39924329的博客 244

java编码中一些值得注意的语法

1. 常量一般用大写,定义成静态的,如 static final PI=3.14152. 静态方法不能访问非静态的方法或非静态的成员变量,反之则可以.3. 特殊变量super提供了对父类的访问,可以使用super访问被子类隐藏的变量或被子类覆盖的方法;每个子类被构造时,都隐式地调用supper(),所以说,父类必须提供相应的构造函数;即子类实例化时,调用了子类的构造方法之前,先调用父类的构

1246

设计代码说明什么是多态性?如何实现多态?(代码中要写注释解释)_写出优质Java代码的4个技巧...

【摘要】如果现在要求对你写的Java代码进行优化,那你会怎么做呢?笔者在本文介绍了可以提高系统性能以及代码可读性的四种方法,如果你对此感兴趣,就让我们一起来看看吧。以下为译文。我们平时的编程任务不外乎就是将相同的技术套件应用到不同的项目中去,对于大多数情况来说,这些技术都是可以满足目标的。然而,有的项目可能需要用到一些特别的技术,因此工程师们得深入研究,去寻找那些最简单但最有效的方法。在前一篇文章...

weixin_39628551的博客 611

关于"多态"static方法的理解

 要强调的是,多态性只发生于方法,而不发生于域.并且,对于方法,只有那些非static与非final方法才具有多态性. 这里讨论的是static方法不能发生多态.值得注意的是,所谓的static方法不能多态指的是:override的方法本身是不是static的,而不是指调用override方法的方法是不是static的!比如以下程序: class Father ...{     p

Forrest He的专栏 1669

java基础】java继承从“我爸是李刚”讲起

前言 本文主要多方面讲解java继承,旨在让初学者通俗易懂,至于“我爸是李刚”,反正楼主也不知道谁爸是李刚。 文章目录1、继承的概述1.1、继承的由来1.2、继承的定义1.3、继承的优点1.4、继承的格式2、关于继承之后的成员变量2.1、成员变量不重名2.2、 成员变量重名2.3、关于继承中成员变量值得思考的一个问题3、关于继承之后的成员方法3.1、成员方法不重名3.2、成员方法重名3.3、继承中...

宜春 1万+

推荐文章:深入理解Java面向对象编程 - oopj

推荐文章:深入理解Java面向对象编程 - oopj 1. 项目介绍 oopj 是一个专为学习和掌握Java面向对象编程而设计的开源项目。它提供了一套完整的培训课程资料,旨在帮助新手和有一定基础的开发者深化对Java OOP的理解并提升编程技能。该项目由经验丰富的讲师维护,并鼓励所有对此感兴趣的人积极参与交流和提问。 2. 项目技术分析 oopj 包含了Java基础到高级特性的全面教程,重点聚焦于...

gitblog_00559的博客 619

JAVA怎样理解面向对象

学习JAVA语言必须掌握类和对象,这样可以从深层次理解JAVA这种面向对象的程序开发理念,从而更好更快地掌握JAVA的编程思想和方法。掌握类和对象是JAVA语言编程的基础。那么,到底什么是类和对象呢,请见下面。 1.现实世界中,随处可见的一种事物就是对象,对象是事物存在的实体,如人类、书桌、计算机、高楼大厦等。人类解决问题的方式总是将复杂的事物简单化,于是就会思考这些对象都是由哪些部分组成的。通...

weixin_30410999的博客 77

Java)《head first java值得Java或面向对象基础的新手看。

看完这本书后本人收获良多。 内容对Java以及面向对象的入门者非常友好。 抽象的内容惯用图解的方法来剖析,通俗易懂 之前看C#入门经典的面向对象时,依然浓浓的一头雾水。 (1)很不解为何实例化要写成A a = new A();     不解为何“A要重复写两次”;     不解为何“等号两边都有A,感觉它就像在说‘A=A’这样的废话一样”; (2)不知道什么是多态性,为什...

arof54503的博客 217

最新版Java面试八股文【值得收藏】

本文总结了最新的java面试题,供求职者快速复习java知识,找的心仪工作

那条大鱼的博客 1698

java面向对象自己的理解_JAVA面向对象理解

做测试也挺久了,大学时没有认真学会java,现在各个企业对测试人员要求越来越高,掌握编程语言的已经成了必备的技能;自己也断断续续学了很多次java,但都没有好好得把java学好,在要面临跳槽时总觉得自己的简历上总是少些亮点。终于下定决心,每天抽出2个钟学习java,为了在以后的简历中可以写上懂得java。一、面向对象现实世界中,随处可见的一种事物就是对象,对象是事物存在的实体,如人类、书桌、计算机...

weixin_42102220的博客 112
上一篇: 找出一个字符串中第一个无重复字符
下一篇: String、StringBuffer和StringBuilder之间比较
lzh3521
博客等级 码龄18年 5粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值