Java基础之多态性
多态性
面向对象特征多态性
* 理解:理解为一个事物的多中形态
* 对象的多态性父类的引用指向子类的对象
* 多态的使用。虚拟方法调用
* 有了对象的多态性以后,在编译期,只能调用父类中声明的方法,但在运行期间实际执行的是子类重写父类的方法
* 总结编译看左边执行看右边
* 多态性使用的前题
*类的继承关系,方法的重写
* 对象的多态性只适应于方法,不适应于属性
*/
https://www.runoob.com/java/java-polymorphism.html
若子类重写父类的方法,就意味着子类里定义的方法彻底覆盖父类的方法,系统不会将父类的方法转移到子类中
2.对于实例变量(属性)则不存在这样的现象,即使子类里定义了于父类完全相同的属性,这个属性也不可能覆盖父类中的属性
父类
1 2 3 4 5 6 7 8 9 10 11 12 13 | package com.chenxi.java4; public class Person { String name; int age; int id = 1100 ; public void eat(){ System.out.println( "人吃饭" ); } public void walk(){ System.out.println( "人走路" ); } } |
子类1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package com.chenxi.java4; public class Man extends Person { boolean isSmoking; int id = 1002 ; public void earnMoney(){ System.out.println( "男人负责养家" ); } public void eat(){ System.out.println( "多吃肉" ); } public void walk(){ System.out.println( "锻炼" ); } } |
子类2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package com.chenxi.java4; public class Woman extends Person { boolean isBeauty; public void goShopping(){ System.out.println( "女人喜欢购物" ); } public void eat(){ System.out.println( "女人少吃" ); } public void walk(){ System.out.println( "女人窈窕的走路" ); } } |
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class PersonTest { public static void main(String[] args) { Person p1 = new Person(); p1.eat(); Man man = new Man(); man.eat(); man.age= 23 ; man.earnMoney(); //对象的多态性,必须时类的子类;父类的应用指向子类的对象 Person p2 = new Man(); //多态性 Person p4 = new Woman(); //多态的使用:当调用子父类同名同参的方法时,实际上执行的时子类重写父类的方法----虚拟方法调用 p2.eat(); //编译的时候看的是父类;执行的时候执行的是子类 // p2.earnMoney(); ((Man) p2).earnMoney(); } } |
测试
1 2 3 4 5 6 7 | 人吃饭 多吃肉 男人负责养家 多吃肉 男人负责养家 Process finished with exit code 0 |
多用性的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | package com.chenxi.java4; /* 多态性的使用 */ public class AnimalTest { public static void main(String[] args) { AnimalTest test = new AnimalTest(); test.func( new Dog()); test.func( new Cat()); } public void func(Animal animal){ //声明Animal animal.eat(); animal.shout(); } } class Animal{ public void eat(){ System.out.println( "吃饭" ); } public void shout(){ System.out.println( "动物叫" ); } } class Dog extends Animal{ @Override public void eat() { System.out.println( "狗吃骨头" ); } @Override public void shout() { System.out.println( "汪" ); } } class Cat extends Animal{ public void eat(){ System.out.println( "猫吃鱼" ); } public void shout(){ System.out.println( "喵喵" ); } } |
测试
1 2 3 4 5 6 | 狗吃骨头 汪 猫吃鱼 喵喵 Process finished with exit code 0 |
重载、重写与多态性的区别
重载定义:在同一个类中,具有相同的方法名,但每个重载的方法具有一个独一无二的参数类型列表(可以是不同的类型,可以是不同的参数个数,也可以是相同的类型不同的顺序),但不能通过返回值去区分重载方法。
重写定义:
条件:继承基类。
定义:覆盖是指导出类去重写基类相同的方法,去扩展基类同名方法,得到自己想要的特定方法内容。若导出类有相同名称的重载方法,可以通过添加标签@override
去声明这是一个覆盖而不是重载。
多态性:
条件:
1、继承基类。
2、重写。
3、父类引用指向子类对象。
定义:
1、多态是允许你将父对象设置成为一个或更多的他的子对象相等的技术(可以理解为这是一种 向上转型)
2、多态方法调用允许一种类型表现出与其他相似类型之间的区别,只要它们都是从同一基类导出而来。
——向上转型
3、同一消息发送可以根据对象的不同从而采取不同的行为方式。
作用:多态的作用是消除类型之间的耦合关系
内容:
1、Java中所有方法(除了static和final)都是通过动态绑定实现多态
2、多态是一项让程序员“将改变的事物与未变的事物分离开来”的重要技术
3、private方法被自动认为是final方法,对导出类是屏蔽的,不能被覆盖、重载。
4、域在编译器进行解析
5、构造器不具有多态性(实际上它们是static方法,声明是隐式的)
好处:
1、改善代码的组织结构和可读性
2、创建可扩展的程序
如果不是晚绑定就不是多态
参考:https://blog.csdn.net/Blank_spaces/article/details/76419166
多态性的对象调用子类特有的属性或者方法
编译的时候看的是父类;执行的时候执行的是子类
不能调用子类所特有的方法、属性;编译时p2是 person类型的
有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的;但由于变量声明为父类类型,导致编译时只能识别父类中的属性和方法
如何才能调用对象多态性后,子类特有的属性和方法
向下转型。使用强制类型转换符
父类子类与上面相同
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | public class PersonTest { public static void main(String[] args) { Person p1 = new Person(); p1.eat(); Man man = new Man(); man.eat(); man.age= 23 ; man.earnMoney(); //对象的多态性,必须时类的子类;父类的应用指向子类的对象 Person p2 = new Man(); //多态性 Person p4 = new Woman(); //多态的使用:当调用子父类同名同参的方法时,实际上执行的时子类重写父类的方法----虚拟方法调用 p2.eat(); //编译的时候看的是父类;执行的时候执行的是子类 //不能调用子类所特有的方法、属性;编译时p2是 person类型的 //有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的 //但由于变量声明为父类类型,导致编译时只能识别父类中的属性和方法 //如何才能调用对象多态性后,子类特有的属性和方法 /*向下转型。使用强制类型转换符 */ System.out.println( "----------------------------------" ); Man m1 = (Man)p2; //强转类型 m1.earnMoney(); } } 测试 人吃饭 多吃肉 男人负责养家 多吃肉 ---------------------------------- 男人负责养家 Process finished with exit code 0 |
instanceof 关键字
instanceof 关键字的使用
a instanceof A 判断对象a是不是类A中的一个实例;如果时返回true,如果不是返回false
使用场景:为了避免向下转型时出现ClassCastException的异常,向下转型之前先进行instanceof的判断
如果a instanceof A 返回True 则 a instanceof B 也返回True;其中类A是类B的父类;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | /** * 面向对象特征多态性 * 理解:理解为一个事物的多中形态 * 对象的多态性父类的引用指向子类的对象 * 多态的使用。虚拟方法调用 * 有了对象的多态性以后,在编译期,只能调用父类中声明的方法,但在运行期间实际执行的是子类重写父类的方法 * 总结编译看左边执行看右边 * 多态性使用的前题 *类的继承关系,方法的重写 * 对象的多态性只适应于方法,不适应于属性 */ public class PersonTest { public static void main(String[] args) { Person p1 = new Person(); p1.eat(); Man man = new Man(); man.eat(); man.age= 23 ; man.earnMoney(); //对象的多态性,必须时类的子类;父类的应用指向子类的对象 Person p2 = new Man(); //多态性 Person p4 = new Woman(); //多态的使用:当调用子父类同名同参的方法时,实际上执行的时子类重写父类的方法----虚拟方法调用 p2.eat(); //编译的时候看的是父类;执行的时候执行的是子类 //不能调用子类所特有的方法、属性;编译时p2是 person类型的 //有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的 //但由于变量声明为父类类型,导致编译时只能识别父类中的属性和方法 //如何才能调用对象多态性后,子类特有的属性和方法 /*向下转型。使用强制类型转换符 */ System.out.println( "----------------------------------" ); Man m1 = (Man)p2; //强转类型 m1.earnMoney(); /* instanceof 关键字的使用 a instanceof A 判断对象a是不是类A中的一个实例 使用场景:为了避免向下转型时出现ClassCastException的异常,向下转型之前先进行 instanceof的判断 */ //instanceof if (p2 instanceof Woman){ Woman w1 = (Woman)p2; System.out.println( "********Woman**" ); } // MyService service = new PortLocator().getPort(); // //invoke business method // service.sayHelloWorldFrom(); if (p2 instanceof Man){ Man m2 = (Man)p2; m2.earnMoney(); System.out.println( "********Man*******" ); } } } |
测试
1 2 3 4 5 6 7 8 | 人吃饭 多吃肉 男人负责养家 多吃肉 ---------------------------------- 男人负责养家 男人负责养家 ********Man******* |
示例
1 2 3 4 5 6 7 8 9 10 | //编译通过运行不通过 //Person p3 = new Woman(); //Man m3 = (Man)p3; //编译通过运行也通过 // Object obj= new Woman(); // Person p = (Person)obj; //编译通过运行不通过 // Person p = new Person(); // Man m = (Man)p; } |
多态性测试
父类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package com.chenxi.exer; public class GeometricObject { protected String color; protected double weight; public String getColor() { return color; } public void setColor(String color) { this .color = color; } public double getWeight() { return weight; } public void setWeight( double weight) { this .weight = weight; } public GeometricObject(String color, double weight){ super (); this .color =color; this .weight= weight; } public double findArea(){ return 0.0 ; } } |
子类1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package com.chenxi.exer; public class GeometricObject { protected String color; protected double weight; public String getColor() { return color; } public void setColor(String color) { this .color = color; } public double getWeight() { return weight; } public void setWeight( double weight) { this .weight = weight; } public GeometricObject(String color, double weight){ super (); this .color =color; this .weight= weight; } public double findArea(){ return 0.0 ; } } |
子类2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | package com.chenxi.exer; public class MyRectangle extends GeometricObject { private double width; private double height; public MyRectangle( double width, double height,String color, double weight){ super (color,weight); this .height= height; this .width= width; } public void setWidth( double width) { this .width = width; } public void setHeight( double height) { this .height = height; } public double getHeight() { return height; } public double getWidth() { return width; } @Override public double findArea() { //return super.findArea(); return width * height; } } |
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | package com.chenxi.exer; /* 定义三个类,父类GeometricObject代表几何形状,子类Circle代表圆形,MyRectangle代表矩形。 定义一个测试类GeometricTest,编写equalsArea方法测试两个对象的面积是否相等(注意方法的参 数类型,利用动态绑定技术),编写displayGeometricObject方法显示对象的面积(注意方法的参 数类型,利用动态绑定技术)。 */ public class GeometricTest { public static void main(String[] args) { GeometricTest test = new GeometricTest(); Circle c1 = new Circle( 3.3 , "white" , 1.0 ); test.displayGeometricObject(c1); Circle c2 = new Circle( 3.3 , "white" , 1.0 ); test.displayGeometricObject(c2); //test.equalsArea(c1,c2); System.out.println(test.equalsArea(c1,c2)); } // public void displayGeometricObject (GeometricObject o){ System.out.println( "面积为" +o.findArea()); } public boolean equalsArea(GeometricObject o1,GeometricObject o2){ return o1.findArea() == o2.findArea(); } } 结果 面积为 34.1946 面积为 34.1946 true Process finished with exit code 0 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
2020-04-08 MySQL 的查询
2019-04-08 docker 镜像仓库的安装与使用