碧辉腾乐 网站建设,wordpress loop,wordpress加密版权,职业培训机构文章目录
一、什么是多态二、重写 2.1、重写的规则 三、多态的实现条件四、向上转型五、向下转型六、动态绑定七、使用多态的优缺点 7.1、优点7.2、缺点 八、避免在构造方法中调用重写的方法
一、什么是多态 Java多态是面向对象编程的一个重要特性#xff0c;它允许不同的对…文章目录一、什么是多态二、重写2.1、重写的规则三、多态的实现条件四、向上转型五、向下转型六、动态绑定七、使用多态的优缺点7.1、优点7.2、缺点八、避免在构造方法中调用重写的方法一、什么是多态Java多态是面向对象编程的一个重要特性它允许不同的对象对同一消息做出不同的响应。具体点就是不同的对象去完成相同的一个任务完成后展现的结果不相同。比如学生在学校里面学习但是学生分为体育生和文化生体育生在学校里面主要学习体能方面的训练技巧文化生在学校里面主要学习文化知识两者在学校里面都是进行学习这一件事但是体育生和文化生学习得到的内容并不相同体育生学习后的结果就是体能方面的提升文化生学习后的结果就是将知识记忆在脑海中两者都是进行学习但是结果并不相同这就是多态。体育生是一个对象文化生是一个对象两个对象完成学习这一件事情得到的结果不相同这是一个多态现象的体现但想要在程序世界实现多态就需要其他的特性的辅助了二、重写重写又称为“覆盖”简单来说就是将原有的方法进行重新编写但是方法名返回类型参数列表必须要相同是子类对父类非静态非private修饰非final修饰非构造方法等谁实现过程进行重新编写即外壳不变内部革新。当子类继承父类并且子类调用从父类继承下来的方法时该方法不适应当前对象的行为又或者是行为类似但不尽相同子类需要重新定义该行为此时就可以将父类继承下来的方法进行重写定义属于自己的特定的行为。 比如说学生类学生对象在学校的行为就是学习当体育生类继承学生类体育生对象调用行为学习但是该行为对于体育生来说不是很完整体育生对象应该是学习体能训练技巧此时我们就可以对行为学习进行重写将其重新定义为学习体能训练技巧。对于已经投入使用的类尽量不要轻易修改避免出现不必要的麻烦。最好的方法就是重新定义一个类来重复利用其中的共性内容并且添加或者改动新的内容。学生类public class Student { protected String name; protected String id; protected int age; public Student(String name, String id, int age) { this.name name; this.id id; this.age age; } public void study() { System.out.println(学生 name 在学习....); } }体育生类public class CulStu extends Student{ public CulStu(String name, String id, int age) { super(name, id, age); } }子类体育生对父类学生类中的行为学习进行重写public class CulStu extends Student{ public CulStu(String name, String id, int age) { super(name, id, age); } Override public void study() {//对父类的行为进行重写 System.out.println(体育生 name 在学习体能训练技巧...); } }2.1、重写的规则1、子类在重写父类方法时必须与父类的原型一致返回类型参数列表方法名要完全一致2、被重写的方法返回类型可以不相同但是必须具有父子类关系3、访问权限不能比被重写的方法的访问权限低就是重写后的方法的访问权限要大于等于被重写的方法的访问权限。例如如果父类方法被public修饰子类中重写方法的访问权限就不能是protected如果被重写方法是被protected修饰那么重写方法只能说public修饰或者是protected修饰。访问权限从小到大0:private 默认权限 protected public4、被重写方法和重写后的方法两者的方法签名是相同的。5、父类中的构造方法、被static修饰的方法、被final修饰的方法被private修饰的方法不可以被重写6、重写的方法可以使用“Override”注解来显示指定该注解可以帮我们校验重写中出现的错误比如将重写方法名编写错了父类中没有对于的方法名那么此时编译会爆红来提示我们重写出现错误。7、只能在子类中进行重写父类的方法被重写方法和重写方法必须构成父子类关系需要注意的是被private修饰的方法不能够被重写的原因并非是访问权限的原因重写后的方法的访问权限要大于等于被重写方法的访问权限这也就意味着访问权限是可以相同的这说明如果被重写方法的访问权限是private的话重写后方法的访问权限也可以说private但实际上这样编写代码还是会爆红被private修饰的方法不能够被重写的原因实际上是因为private修饰符本身被private修饰的方法是私有型方法只允许在本类中调用拥有父子类关系也不可以调用而且重写后方法和被重写方法的方法签名是一样的那说明这两者是同一个方法。因此被private修饰的方法是不可重写的三、多态的实现条件在Java中要实现多态必须要满足以下几点1、必须要含有父子类关系2、子类中要重写父类的方法3、通过父类的引用调用重写的方法多态的体现在代码允许的时候当传递不同的对象时会调用对应类中的方法体育生类public class PEstu extends Student{ public PEstu(String name, String id, int age) { super(name, id, age); } Override public void study() { System.out.println(体育生 name 在学习体能训练技巧...); } }文化生类public class CulStu extends Student{ public CulStu(String name, String id, int age) { super(name, id, age); } Override public void study() {//对父类的行为进行重写 System.out.println(文化生 name 在学习文化知识...); } }学生类public class Student { protected String name; protected String id; protected int age; public Student(String name, String id, int age) { this.name name; this.id id; this.age age; } public void study() { System.out.println(学生 name 在学习....); } }public class Main { public static void func(Student student) { student.study(); } public static void main(String[] args) { Student student1 new CulStu(文化生,1111,18); func(student1); Student student2 new PEstu(体育生,2222,18); func(student2); } }当编译器在编译的时候func方法并不知道会传递什么对象也不知道会调用体育生类还是文化生类中的方法只有等程序运行起来才知道会传递什么对象给方法才知道会调用哪个类中的方法需要注意的是此时必须要使用父类的引用func方法的形参必须是父类类型的才可以。因为形参sdutens引用引用的对象不同所以调用同一个study方法时所表现的形式不一样我们把这个情况称之为多态。不同的对象做同一件事情所表现的结果不同第一次调用func方法时传递的是文化生类这个对象studennt这个引用就指向文化生对象此时student调用study方法就会调用子类中重写的syudy方法从而打印出”文化生 name 在学习文化知识…第二次调用func方法时传递的是体育生类这个对象studennt这个引用就指向体育生对象此时student调用study方法就会调用子类中重写的syudy方法从而打印出”体育生 name 在学习文化知识…在上述代码中前三个类是由类的实现者编写的最后一个类是类的调用者编写的。当类的调用者在编写func这个方法的时候参数类型是Student父类方法内部本身并不知道也不关注将来会传递什么对象给student引用进行指向此时studengt这个引用调用study方法可能会有多种不同的表现这种行为就称为多态。四、向上转型在实例化对象时我们一般是这样编写的Student studengt new Student();但是我们看上面的代码会发现并不是这样编写的而是使用父类类型的引用来指向子类类型的对象Student student1 new CulStu(文化生,1111,18);这就是向上转型。向上转型创建一个子类对象将其当做父类对象来使用语法格式 父类类型 对象名 new 子类类型();父类类型的引用指向了子类对象Student是父类CulStu是子类父类类型是可以引用子类对象的我们知道继承本质上是is-a的关系体育生是学生也是is-a的关系。Student student1 new CulStu(文化生,1111,18);文化生是学生Student student1 new CulStu(体育生生,1111,18);体育生是学生向上转型的使用场景有三个1、直接赋值2、方法传递3、方法返回Student student1 new CulStu(体育生生,1111,18);//1、直接传递public static void func(Student student) {//2、方法传递 //将方法的参数类型设置为父类类型 }public static Student func() {//3、方法返回 return student;//将方法的返回值设置为父类类型 }向上转型的优点让代码变得更加灵活缺点该引用无法调用子类的特有的方法因为引用是父类类型的引用本身就只能调用本类型的方法变量无法调用子类的方法变量五、向下转型我们实现向上转型后只能通过父类的引用调用父类的方法或者访问父类的变量当我们需要调用子类的方法或者访问子类的变量时又该如何重新new一个子类对象吗不现实如果重新new一个子类那么和之前的子类对象就是两个对象这两个对象之间是没有联系的。此时我们可以通过向下转型将父类引用还原为子类引用再通过该引用调用子类方法或访问变量即可。但需要注意的是将父类引用还原为子类引用是一个强制转换的过程因为向上转型是符合is-a关系的体育生类是学生类没有问题父类引用 子类对象但此时我们是将父类引用转换为子类对象相当于是将父类引用赋予给子类对象学生类是体育生类这似乎不太符合常理吧并非所有学生类都是体育生类因此相当于是非is-a的关系而是a-is的关系有点倒反天罡啊因此此处需要强制类型转换public static void main(String[] args) { Student student new CulStu(文化生,1111,18); CulStu culStu (CulStu) student;//将父类引用强转为子类引用 culStu.a 嘻嘻; culStu.fun(); }将父类引用强转为子类引用后此时子类引用指向之前被父类引用指向的子类对象也就是说现在是子类引用指向子类对象即可通过子类引用访问子类变量调用子类方法了。但是还有特别需要注意的向上转型时父类引用指向体育生子类对象当我们需要向下转换时该父类引用只能强转为体育生子类引用不可以将父类引用强转为文化生子类引用否则会编译报错。此时父类引用指向文化生子类对象但是却将父类引用强转为体育生子类引用引用类型不对结果编译就报错了并没有语法上的错误。因此我们需要强转的时候就需要先判断此时的父类引用得到是指向哪个子类对象我们需要用到instanceof关键字该关键字可以判断引用是否指向该类的对象。引用名 instanceof 类名;//判断引用是否指向该类对象指向则返回true否则放false再配合上if语句即可判断并执行强转代码了。public static void main(String[] args) { Student student new CulStu(文化生,1111,18); if(student instanceof CulStu) {//判断student引用是否指向Culstu类对象 CulStu culStu (CulStu) student; culStu.study(); } if(student instanceof PEstu) {//判断student引用是否指向PEstu类对象 PEstu pEstu (PEstu) student; pEstu.study(); } }一般向下转型使用比较少因为涉及到强制类型转换强转是不安全的有可能会导致数据的丢失这个是我们无法预知的因此不到迫不得已不要出现强转的代码。六、动态绑定public class Main { public static void func(Student student) { student.study(); } public static void main(String[] args) { Student student1 new CulStu(文化生,1111,18); func(student1); Student student2 new PEstu(体育生,2222,18); func(student2); } }动态绑定又称之为运行时绑定。大家可能会好奇在func方法中明明是通过父类的引用去调用study方法但是最终显示的结果却是子类中重写的study方法的结果也就是说程序并非调用父类的study方法而是调用子类的study方法通过反汇编查看汇编代码确实是调用父类的study方法但是在运行的时候却调用了子类重写的study方法这个过程称之为运行时绑定又称动态绑定。在代码运行的时候父类的study方法被绑定到了子类中重写的study方法中。动态绑定又称为运行时绑定在程序编译的时候不能确定方法的行为结果只有当程序运行的时候才能够确定具体调用哪个类的方法。典型代表是方法重写又称后期绑定静态绑定在编译的时候编译器通过用户传递的实参类型就可以确定具体调用哪个方法。典型代表是方法重载又称前期绑定七、使用多态的优缺点7.1、优点使用多态的好处1、可以降低圈复杂度圈复杂度是一种描述一段代码复杂程度的方式一段代码如果平铺直叙那么就很容易理解如果加上大量的if语句循环语句就会导致理解起来很复杂。因此我们可以简单粗暴的计算一段代码中条件语句和循环语句出现的个数这个个数就称之为圈复杂度。当代码中没有条件语句和循环语句时代码直接从头到尾一条路径执行那么圈复杂度为1如果代码中有一个if语句那么此时代码出现了两种路径那么圈复杂度为2。如果一个方法的圈复杂度太高那么就需要考虑重构了而使用多态通过运行时绑定能够避免使用if语句还可以调用重写后有特殊要求的方法从而降低代码的圈复杂度。此时有以下代码class Shape { public void draw() { System.out.println(画图形); } } class Rect extends Shape { Override public void draw() { System.out.println(画菱形); } } class Cycle extends Shape{ Override public void draw() { System.out.println(画圆形); } } class Flower extends Shape { Override public void draw() { System.out.println(画一朵花); } } public class Main { }现在我们需要打印两朵花两个圆形一个菱形我们可以用到数组1、不使用多态打印public class Main { public static void main(String[] args) { Rect rect new Rect(); Cycle cycle new Cycle(); Flower flower new Flower(); String[] str {Flower,Flower,Cycle,Cycle,Rect}; for (String s:str) { if(s.equals(Flower)) { flower.draw(); } else if (s.equals(Cycle)) { cycle.draw(); } else { rect.draw(); } } } }2、使用多态打印public static void main(String[] args) { Shape rect new Rect(); Shape cycle new Cycle(); Shape flower new Flower(); Shape[] shapes {flower,flower,cycle,cycle,rect}; for (Shape shape : shapes) { shape.draw(); } }观察两个代码不难看出不使用多态打印的代码大量使用条件语句和循环语句那么伴随着圈复杂度提高代码的可阅读性降低。2、可扩展能力强如果此时需要增加打印比如增加打印一个正方形我们需要新定义一个正方形类在不使用多态的情况下需要在条件语句和循环语句上进行更改需要做大量的修改操作改动成本高如果是使用多态的方法打印那么我们只需要在数组里面增加指向正方形类对象的父类引用即可代码的改动较小效率高。public static void main(String[] args) { Shape rect new Rect(); Shape cycle new Cycle(); Shape flower new Flower(); Shape[] shapes {flower,flower,cycle,cycle,rect,square}; for (Shape shape : shapes) { shape.draw(); } }7.2、缺点多态的缺点代码的运行效率降低1、属性没有多态性当父类和子类同时有同名属性的时候通过父类引用只能调用父类的成员属性2、构造方法没有多态性八、避免在构造方法中调用重写的方法class A { public A() { func(); } public void func() { System.out.println(A.func()); } } class B extends A{ private int num 1; Override public void func() { System.out.println(B.func() num); } } public class Test { public static void main(String[] args) { A a new B(); } }仔细观察这一段代码会打印什么结果首先调用子类的构造方法在子类中的构造方法会先通过super( )调用父类的构造方法但是在执行构造方法之前需要先执行构造代码块调用父类的构造方法过程中再调用func()方法此时满足动态绑定的条件在继承体系下子类中重写父类的方法调用重写的方法。发生动态绑定调用子类中重写的func()方法因为此时父类的构造方法还没执行完成子类的构造代码块和构造方法就没有得以执行因此子类中的成语变量处于未初始化状态因此动态绑定调用子类重写的func()方法方法里面打印子类未初始化的成员变量num重写的func()方法执行完后父类的构造方法也执行完毕接下来执行子类的构造代码块将num赋值为1再执行子类的构造方法。因此程序最终打印结果为0。用尽量简单的方式使对象进入可工作状态 用尽量简单的方式使对象进入可工作状态 用尽量简单的方式使对象进入可工作状态尽量不要在构造器构造方法、构造代码块中调用方法如果这个方法被子类重写构造器内就会触发动态绑定从而调用子类中重写的构造方法但是此时子类对象还没有构造完成因此该过程就有可能会触发一些引用又极难发现的问题。因此在构造器中最好不调用方法只对成员变量进行初始化即可。Java程序员如今深陷技术迭代放缓与行业需求收缩的双重困境职业发展空间正被新兴技术浪潮持续挤压。面对当前Java程序员可能面临的“发展瓶颈”或行业挑战更积极的应对策略可以围绕技术升级、方向转型、能力拓展三个核心展开而非被动接受“不行”的标签通过调查对比我发现人工智能大模型是个很好的出路。技术升级与转型机会突破传统Java开发边界大模型技术的普及为Java开发者提供了新的机遇使他们能够突破传统企业级开发的局限进入人工智能这一高增长领域。通过学习大模型集成Java开发者可以转型为AI应用开发者拓展职业发展空间。技术栈升级Java社区积极拥抱大模型技术推出了多个开源项目和框架如Deeplearning4j、DJLDeep Java Library等。这些工具为Java开发者提供了丰富的资源使他们能够更方便地构建和部署基于大模型的应用。发挥Java在企业级应用中的优势稳定性与可靠性Java作为企业级应用的主流语言其稳定性和可靠性在大模型应用中同样得到体现。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大模型学习资源包》免费分享