Java多态的理解
一、多态在类和接口中的使用
1.类:父类的引用指向子类对象
Animal animal = new Dog( );
2.接口:接口引用指向实现类的对象
Java中,接口和类是并列的两个结构,接口可以理解为特殊的抽象类
UserDao userDao = new UserDaoImpl( );
二、在开发中的使用
在我们使用集合类时总是这样定义:
List<?> list= new ArrayList<?>
Map<?,?> map = new HashMap<?,?>
为什么?因为List是ArrayList的接口,Map是HashMap的接口。
这样用有什么好处呢?
当定义List list;时只是在栈区开辟一个空间放list引用,此时并没有创建对象。
所以不知道是ArrayList还是LinkedList等具体的实现类。
当你 list= new ArrayList(); 就创建了ArrayList对象。并且把刚开始创建的list引用指向堆空间的这个ArrayList对象。
为什么一般都使用 List list = new ArrayList() ,而不用 ArrayList alist = new ArrayList()呢?
这就是多态的思想。
由于List接口有多个实现类,如 ArrayList、LinkedList和Vector等,目前你用的是ArrayList,也许哪一天你需要换成其它的实现类呢?
这时你只要改变这一行就行了:List list = new LinkedList(); 其它使用了list地方的代码根本不需要改动。
假设你开始用 ArrayList arrayList = new ArrayList(), 这下你将改动所有运用到ArrayList对象的地方,特别是如果你使用了 ArrayList特有的方法和属性。
所以为了便于程序代码的重构,如果没有特别需求的话,最好使用List list = new LinkedList(); 定义。这就是面向接口编程的好处。
注意事项!!!
此时定义的list对象只能使用ArrayList中已经实现了List接口中的方法(即接口和实现类共有的方法),ArrayList中那些自有的、没有在List接口定义的方法是不可以被访问到的。比如list.add()其实是List接口的抽象方法,但是调用ArrayList的方法如 clone()方法是调用不到的。
接口的灵活性就在于“规定一个实现类必须做什么,而不管你如何做”。我们可以定义一个接口类型的引用变量来引用实现接口的实现类的实例,当这个引用调用方法时,它会根据实际引用的类的实例来判断具体调用哪个方法(多态体现),这和上述的父类的引用访问子类的对象的机制相似。
关于对象的多态性,我们在编译期,只能调用父类中声明的方法。但在运行期,我们实际执行的是子类重写父类的方法。
类的继承关系和方法的重写是多态的使用前提!
比如:Person p = new Man();
编译,看左边;运行,看右边(属性除外)。
即对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)
三、关于向上转型与向下转型:
向上转型:多态 Person p = new Man();
向下转型: Order order = (Order)obj;
使用多态进行程序设计的核心技术之一就是使用向上转型对象:
即将abstract类声明对象作为其子类的向上转型对象,那么这个向上转型对象就可以调用子类重写的方法
当absctract类声明对象按实际引用不同的子类对象时,就能达到以一变应万变的目的
为什么使用向下转型:
有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。如何才能调用子类特的属性和方法?使用向下转型。
如何实现向下转型:
使用强制类型转换符:( )
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY