文章目录
- 一、什么是多态
- 二、多态实现的条件
- 三、重写
- 3.1 什么是重写
- 3.2 重写和重载的区别
- 四、向上转型和向下转型
- 4.1 向上转型
- 4.2 向下转型
- 五、多态的优缺点
- 六、避免在构造方法中调用重写的方法
一、什么是多态
在Java中,多态是面向对象编程中的一个重要概念,它允许不同类型的对象对同一方法进行不同的实现。具体来说,多态性指的是通过父类的引用变量来引用子类的对象,从而实现对不同对象的统一操作。
例如:狗和猫都是动物,动物共同的行为都有吃这个动作,而狗可以表现为啃骨头,猫则可以表现为吃老鼠。这就是多态的表现,即同一件事情,发生在不同对象的身上,就会产生不同的结果。
二、多态实现的条件
在Java中,要实现多态性,就必须满足以下条件:
继承关系
存在继承关系的类之间才能够使用多态性。多态性通常通过一个父类用变量引用子类对象来实现。方法重写
子类必须重写(Override)父类的方法。通过在子类中重新定义和实现父类的方法,可以根据子类的特点行为改变这个方法的行为,如猫和狗吃东西的独特行为。父类引用指向子类对象
使用父类的引用变量来引用子类对象。这样可以实现对不同类型的对象的统一操作,而具体调用哪个子类的方法会在运行时多态决定
例如,下面的案例是根据猫和狗叫的动作的不同,而实现的多态:
class Animal { public void sound() { System.out.println("动物发出声音"); } } class Dog extends Animal { @Override public void sound() { System.out.println("狗发出汪汪声"); } } class Cat extends Animal { @Override public void sound() { System.out.println("猫发出喵喵声"); } } public class Main { public static void main(String[] args) { Animal animal1 = new Dog(); // 父类引用指向子类对象 Animal animal2 = new Cat(); // 父类引用指向子类对象 animal1.sound(); // 输出:狗发出汪汪声 animal2.sound(); // 输出:猫发出喵喵声 } }在这个示例中,Animal类是父类,Dog和Cat类是它的子类。通过将父类的引用变量分别指向子类对象,实现了多态性。在运行时,根据引用变量的实际类型来调用相应的子类方法,从而输出不同的声音。
三、重写
3.1 什么是重写
在面向对象编程中,重写(Override)指的是子类重新定义和实现了从父类继承而来的方法,以改变方法的行为。子类通过重写方法可以提供自己特定的实现,使得父类方法的行为在子类对象的身上有不同的表现。
想要理解方法重写,需要知道以下概念:
继承关系
重写方法是基于父类和子类之间的继承关系。子类继承了父类的方法,包括方法的名称、参数列表和返回类型。方法签名
重写的方法与父类的方法具有相同的方法签名,即方法的名称、参数列表和返回类型必须一致(当然,如果返回类型的对象本身的类型则可以不同,但是必须要有继承关系)。方法签名不包括方法体。@Override注解
为了明确表明这是一个重写的方法,可以使用@Override注解来标记子类中的方法。该注解会在编译时检查是否满足重写条件,如果不满足会报错。动态绑定
通过父类引用变量调用被子类重写的方法时,会根据实际引用的对象类型,在运行时动态绑定到相应的子类方法。
方法重写的规则:
方法名称、参数列表和返回类型必须与父类中被重写的方法相同。
子类重写的方法的访问修饰符的权限不能低于父类中被重写方法的访问修饰符权限。例如:如果父类方法被
public修饰,则子类中重写该方法就不能声明为protected。重写的方法不能抛出比父类中被重写的方法更多或更宽泛的异常。子类中重写的方法可以抛出相同的异常或更具体的异常,或者不抛出异常。
- 例如,如果父类的方法声明抛出
IOException,则子类中重写的方法可以抛出IOException或FileNotFoundException,或者不抛出异常,但不能抛出比IOException更通用的异常,如Exception。
- 例如,如果父类的方法声明抛出
重写的方法必须具有相同的方法体,或者可以进行方法体的扩展。
- 子类中重写的方法可以调用父类中被重写的方法,使用
super关键字。
- 子类中重写的方法可以调用父类中被重写的方法,使用
3.2 重写和重载的区别
首先回顾重载的实现条件:
- 方法名称相同:重载的方法必须具有相同的名称。
- 参数列表不同:重载的方法的参数列表必须不同。参数列表可以通过参数的类型、个数或顺序的不同来区分重载方法。
- 返回类型可以相同也可以不同:重载的方法可以具有相同的返回类型,也可以具有不同的返回类型。返回类型不是重载方法的区分标准。
- 方法所在的类中:重载方法必须定义在同一个类中。
- 方法的访问修饰符和异常:重载方法可以具有相同的访问修饰符(如
public、private、protected)和抛出的异常。
重写和重载的区别:
重写(Override)和重载(Overload)是Java中两个不同的概念,它们在方法的处理方式和实现上有所不同。
重载(Overload)指的是在同一个类中,根据方法的参数列表的不同,定义多个具有相同名称但参数类型或个数不同的方法。重载的方法具有相同的名称,但方法签名不同。
重写(Override)指的是子类重新定义和实现了从父类中继承的方法。重写的方法具有与父类方法相同的名称、参数列表和返回类型。
下面是重写和重载的区别:
定义位置:重载方法定义在同一个类中,而重写方法定义在父类和子类之间。
方法签名:重载方法具有相同的名称,但方法签名(参数类型和个数)不同。重写方法具有相同的名称和方法签名。
继承关系:重载方法不涉及继承关系,可以在同一个类中定义。重写方法是在子类中对父类方法的重新定义和实现。
运行时调用:重载方法是根据方法的参数列表的不同进行静态绑定,在编译时确定。重写方法是根据对象的实际类型进行动态绑定,在运行时确定。
目的:重载方法用于在同一个类中实现相似功能但具有不同参数的方法。重写方法用于子类重新定义父类方法的行为,以适应子类的特定需求。
总结来说,重载是在同一个类中根据参数列表的不同定义多个具有相同名称但参数不同的方法,而重写是子类重新定义和实现了从父类继承的方法。重载方法通过静态绑定在编译时确定调用,重写方法通过动态绑定在运行时确定调用。重载用于实现相似功能但具有不同参数的方法,重写用于改变父类方法的行为以适应子类的需求。
四、向上转型和向下转型
4.1 向上转型
向上转型(Upcasting)是指将一个子类的对象引用赋值给其父类类型的引用变量。这是在面向对象编程中的一种常见操作,用于实现多态性和灵活的对象处理。
在向上转型中,子类对象可以被视为父类对象,可以使用父类类型的引用变量来引用子类对象。这样做的好处是可以以统一的方式处理不同类型的对象,实现代码的灵活性和可扩展性。
向上转型的特点和规则如下:
子类对象可以隐式地转型为父类对象,不需要任何显式的类型转换操作。
父类引用变量可以引用子类对象,但通过父类引用变量只能访问到子类对象中定义的父类成员,无法访问子类独有的成员。
子类对象中重写的方法,在通过父类引用变量调用时,会调用子类中的实现(动态绑定)。
向上转型是安全的操作,因为子类对象本身就是一个父类对象。
下面是一个简单的示例代码,展示了向上转型的使用:
class Animal { public void eat() { System.out.println("Animal is eating."); } } class Dog extends Animal { @Override public void eat() { System.out.println("Dog is eating."); } public void bark() { System.out.println("Dog is barking."); } } public class Main { public static void main(String[] args) { Animal animal = new Dog(); // 向上转型 animal.eat(); // 调用的是 Dog 类中的 eat() 方法 // animal.bark(); // 错误:无法访问 Dog 类中独有的方法 Dog dog = (Dog) animal; // 向下转型 dog.bark(); // 调用 Dog 类中的 bark() 方法 } }在上述示例中,存在一个继承关系:类Dog继承自类Animal。在Main类的main方法中,首先创建了一个Dog类的对象,并将其赋值给一个Animal类型的引用变量animal,这就是向上转型的过程。通过animal引用变量,可以调用eat()方法,而在运行时,实际执行的是Dog类中重写的eat()方法。
需要注意的是,虽然animal引用变量的类型是Animal,但是它指向的是一个Dog类的对象,因此可以将其重新转型为Dog类型(向下转型),并通过dog引用变量访问Dog类中独有的成员方法bark()。
总结起来,向上转型允许将子类对象视为父类对象,以父类类型的引用变量来引用子类对象,实现多态性和灵活的对象处理。
4.2 向下转型
向下转型(Downcasting)是指将一个父类类型的引用变量转换为其子类类型的引用变量。它与向上转型相反,需要进行显式的类型转换操作。
在某些情况下,当一个对象被向上转型后,它的具体类型信息会丢失,只保留了父类类型的信息。如果我们需要访问子类中特有的成员或调用子类重写的方法,就需要使用向下转型。
需要注意的是,向下转型是有风险的,因为转换的对象必须是实际上是子类对象才能成功,否则会在运行时抛出ClassCastException异常。
下面是一个示例代码,展示了向下转型的使用:
class Animal { public void eat() { System.out.println("Animal is eating."); } } class Dog extends Animal { @Override public void eat() { System.out.println("Dog is eating."); } public void bark() { System.out.println("Dog is barking."); } } public class Main { public static void main(String[] args) { Animal animal = new Dog(); // 向上转型 // 使用向下转型之前,需要先检查对象是否实际上是子类的实例 if (animal instanceof Dog) { Dog dog = (Dog) animal; // 向下转型 dog.bark(); // 调用 Dog 类中的 bark() 方法 } else { System.out.println("animal is not an instance of Dog"); } } }在上述示例中,首先创建了一个Dog类的对象,并将其赋值给一个Animal类型的引用变量animal,这就是向上转型的过程。然后,通过使用instanceof运算符检查animal是否是Dog类的实例,以确保进行向下转型时的类型安全。
如果animal是Dog类的实例,那么可以将其转型为Dog类型,并使用dog引用变量调用Dog类中特有的方法bark()。如果animal不是Dog类的实例,则可以根据实际需求进行相应的处理。
需要注意的是,在进行向下转型之前,一定要确保对象实际上是子类的实例,否则会导致ClassCastException异常。因此,在进行向下转型之前,应该使用instanceof运算符进行类型检查,以避免出现异常情况。
五、多态的优缺点
Java多态性的优点:
灵活性和可扩展性:多态性使得代码具有更高的灵活性和可扩展性。通过使用父类类型的引用变量,可以以统一的方式处理不同类型的对象,无需针对每个具体的子类编写特定的代码。
代码复用:多态性可以促进代码的复用。可以将通用的操作定义在父类中,然后由子类继承并重写这些操作。这样一来,多个子类可以共享相同的代码逻辑,减少了重复编写代码的工作量。
可替换性:多态性允许将一个对象替换为其子类的对象,而不会影响程序的其他部分。这种可替换性使得系统更加灵活和可维护,可以方便地添加新的子类或修改现有的子类,而无需修改使用父类的代码。
代码扩展性:通过引入新的子类,可以扩展现有的代码功能,而无需修改现有的代码。这种可扩展性使得系统在需求变化时更加容易适应和扩展。
Java多态性的缺点:
运行时性能损失:多态性需要在运行时进行方法的动态绑定,这会带来一定的性能损失。相比于直接调用具体的子类方法,多态性需要在运行时确定要调用的方法,导致额外的开销。
代码可读性下降:多态性使得代码的行为变得更加动态和不确定。在某些情况下,可能需要跟踪代码中使用的对象类型和具体的方法实现,这可能降低代码的可读性和理解性。
限制访问子类特有成员:通过父类类型的引用变量,只能访问父类及其继承的成员,无法直接访问子类特有的成员。如果需要访问子类特有的成员,就需要进行向下转型操作,这增加了代码的复杂性和维护的难度。
虽然多态性具有一些缺点,但在大多数情况下,其优点远远超过缺点,使得代码更具灵活性、可扩展性和可维护性。因此,多态性在Java编程中被广泛应用。
六、避免在构造方法中调用重写的方法
先来看一段代码:
class B { public B() { // do nothing func(); } public void func() { System.out.println("B.func()"); } } class D extends B { private int num = 1; @Override public void func() { System.out.println("D.func() " + num); } } public class Test { public static void main(String[] args) { D d = new D(); } }上面这段代码的运行结果是:D.func 0,其原因如下:
- 构造 D 对象的同时, 会调用 B 的构造方法。
- B 的构造方法中调用了
func方法, 此时会触发动态绑定, 会调用到 D 中的func方法。- 此时 D 对象自身还没有构造,因此
num处在未初始化的状态,其值为 0。 如果具备多态性,num的值则应该是1。- 所以在构造函数内,尽量避免使用实例方法,除了
final和private方法。
通过上面的例子告诉我们一个道理,那就是:“用尽量简单的方式使对象进入可工作状态”,尽量不要在构造器中调用方法(如果这个方法被子类重写,就会触发动态绑定,但是此时子类对象还没构造完成),可能会出现一些隐藏的但是又极难发现的问题。
Java开发的就业市场正在经历结构性调整,竞争日益激烈
传统纯业务开发岗位(如仅完成增删改查业务的后端工程师)的需求,特别是入门级岗位,正显著萎缩。随着企业技术需求升级,市场对Java人才的要求已从通用技能转向了更深入的领域经验(如云原生、微服务)或前沿的AI集成能力。这也导致岗位竞争加剧,在一、二线城市,求职者不仅面临技术内卷,还需应对学历与项目经验的高门槛。
大模型为核心的AI领域正展现出前所未有的就业热度与人才红利
2025年,AI相关新发岗位数量同比激增543%,单月增幅最高超过11倍,大模型算法工程师位居热门岗位前列。行业顶尖人才的供需严重失衡,议价能力极强,跳槽薪资涨幅可达30%-50%。值得注意的是,市场并非单纯青睐算法研究员,而是急需能将大模型能力落地于复杂业务系统的工程人才。这使得具备企业级架构思维和复杂系统整合经验的Java工程师,在向“Java+大模型”复合人才转型时拥有独特优势,成为企业竞相争夺的对象,其薪资天花板也远高于传统Java岗位。
说真的,这两年看着身边一个个搞Java、C++、前端、数据、架构的开始卷大模型,挺唏嘘的。大家最开始都是写接口、搞Spring Boot、连数据库、配Redis,稳稳当当过日子。
结果GPT、DeepSeek火了之后,整条线上的人都开始有点慌了,大家都在想:“我是不是要学大模型,不然这饭碗还能保多久?”
先给出最直接的答案:一定要把现有的技术和大模型结合起来,而不是抛弃你们现有技术!掌握AI能力的Java工程师比纯Java岗要吃香的多。
即使现在裁员、降薪、团队解散的比比皆是……但后续的趋势一定是AI应用落地!大模型方向才是实现职业升级、提升薪资待遇的绝佳机遇!
如何学习AGI大模型?
作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
2025最新版CSDN大礼包:《AGI大模型学习资源包》免费分享**
一、2025最新大模型学习路线
一个明确的学习路线可以帮助新人了解从哪里开始,按照什么顺序学习,以及需要掌握哪些知识点。大模型领域涉及的知识点非常广泛,没有明确的学习路线可能会导致新人感到迷茫,不知道应该专注于哪些内容。
我们把学习路线分成L1到L4四个阶段,一步步带你从入门到进阶,从理论到实战。
L1级别:AI大模型时代的华丽登场
L1阶段:我们会去了解大模型的基础知识,以及大模型在各个行业的应用和分析;学习理解大模型的核心原理,关键技术,以及大模型应用场景;通过理论原理结合多个项目实战,从提示工程基础到提示工程进阶,掌握Prompt提示工程。
L2级别:AI大模型RAG应用开发工程
L2阶段是我们的AI大模型RAG应用开发工程,我们会去学习RAG检索增强生成:包括Naive RAG、Advanced-RAG以及RAG性能评估,还有GraphRAG在内的多个RAG热门项目的分析。
L3级别:大模型Agent应用架构进阶实践
L3阶段:大模型Agent应用架构进阶实现,我们会去学习LangChain、 LIamaIndex框架,也会学习到AutoGPT、 MetaGPT等多Agent系统,打造我们自己的Agent智能体;同时还可以学习到包括Coze、Dify在内的可视化工具的使用。
L4级别:大模型微调与私有化部署
L4阶段:大模型的微调和私有化部署,我们会更加深入的探讨Transformer架构,学习大模型的微调技术,利用DeepSpeed、Lamam Factory等工具快速进行模型微调;并通过Ollama、vLLM等推理部署框架,实现模型的快速部署。
整个大模型学习路线L1主要是对大模型的理论基础、生态以及提示词他的一个学习掌握;而L3 L4更多的是通过项目实战来掌握大模型的应用开发,针对以上大模型的学习路线我们也整理了对应的学习视频教程,和配套的学习资料。
二、大模型经典PDF书籍
书籍和学习文档资料是学习大模型过程中必不可少的,我们精选了一系列深入探讨大模型技术的书籍和学习文档,它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础。(书籍含电子版PDF)
三、大模型视频教程
对于很多自学或者没有基础的同学来说,书籍这些纯文字类的学习教材会觉得比较晦涩难以理解,因此,我们提供了丰富的大模型视频教程,以动态、形象的方式展示技术概念,帮助你更快、更轻松地掌握核心知识。
四、大模型项目实战
学以致用,当你的理论知识积累到一定程度,就需要通过项目实战,在实际操作中检验和巩固你所学到的知识,同时为你找工作和职业发展打下坚实的基础。
五、大模型面试题
面试不仅是技术的较量,更需要充分的准备。
在你已经掌握了大模型技术之后,就需要开始准备面试,我们将提供精心整理的大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
2025最新版CSDN大礼包:《AGI大模型学习资源包》免费分享