附录:Java 中的重写、重载与注解¶
☕ 课前导语:为什么需要补给?
在马上要开始的 Web 开发实战中,你可能会经常遇到一些似曾相识却又说不清楚的语法:
为什么有的方法名字一样却不报错?为什么子类里的方法头上要顶着一个 @Override?我们在写网页后台时,挂在类头顶上的 @WebServlet 到底是个啥魔法?
别慌!这篇附录专为刚入门 Java 的你准备。我们将用最通俗的语言,带你迅速攻克 Java 开发必用的三大核心概念:重载 (Overload)、重写 (Override) 和 注解 (Annotation)。
🎭 一、重载 (Overloading):同名不同躯的“多面手”¶
1. 什么是重载?¶
重载 (Overload) 发生在一个类里面。指的是你可以写多个名字完全相同的方法,只要它们的参数列表不同(参数的个数、类型或者顺序不同)即可。
💡 生活比喻: 就像一个名叫“做饭 (
cook)”的厨师:
- 你给他面条,他就给你做一碗牛肉面cook(Noodle n)。
- 你给他米饭和鸡蛋,他就给你做蛋炒饭cook(Rice r, Egg e)。
厨师的名字都叫cook,但他会根据你给的材料(参数)不同,做出不同的反应。
2. 代码演示¶
避坑指南
重载只看方法名和参数列表,和方法的“返回值类型”没有任何关系!
如果你写了 public int add(int a) 和 public double add(int a),编译器会直接报错。
🧬 二、重写 (Overriding):青出于蓝的“子类逆袭”¶
1. 什么是重写?¶
重写 (Override) 发生在父类与子类(或接口与实现类)之间。当子类对父类中已经存在的方法不满意时,可以照抄父类的方法签名(名字、参数完全一样),但是重新编写里面的代码逻辑。
💡 生活比喻: 你的老爸(父类)传给你了一家面馆,里面有一道祖传菜叫
makeSoup()(熬汤),老配方是用猪骨熬。 你接手后觉得太油腻了,于是你保留了makeSoup()这个招牌(方法名不变),但是在后厨把做法改成了用牛骨熬(重写了方法体)。
2. 代码演示:面馆的传承与创新¶
3. 进阶实战:重写带来的“多态”魔法¶
理解了重写,我们来看一个在框架底层极为常见的“神仙操作”。假设我们有这样一个场景:
现在,我们在 main 方法中运行以下代码,你猜猜会输出什么?
运行结果:
🕵️♂️ 揭秘时刻(动态绑定):
当你调用 teacher.callEat() 时,因为 Teacher 类里没有写这个方法,程序会去父类 Person 里找,并且开始执行 Person 里的 callEat()。
最神奇的地方在于:当父类的 callEat() 执行到内部的 eat() 时,Java 虚拟机(JVM)非常聪明,它在运行期间发现,“虽然我现在在父类的代码里,但实际让我干活的是一个 Teacher 对象!” 于是,它果断地动态绑定到了子类 Teacher 重写后的 eat() 方法上。
这就是面向对象三大特性之一——多态的魅力!掌握了这个机制,以后看框架底层代码(比如模板方法模式)就会豁然开朗。
⚔️ 三、核心对比:重载 vs 重写 (面试高频题!)¶
为了方便记忆,请把下面这个表格印在脑子里:
| 维度 | 重载 (Overload) | 重写 (Override) |
|---|---|---|
| 发生位置 | 同一个类中 | 子类与父类之间 |
| 方法名 | 必须相同 | 必须相同 |
| 参数列表 | 必须不同 (个数/类型/顺序) | 必须相同 |
| 返回值类型 | 无所谓 | 必须相同 (或是其子类) |
| 通俗理解 | 一个方法的多种表现形式 (多面手) | 子类改造父类的方法 (青出于蓝) |
🏷️ 四、注解 (Annotation):代码里的“神奇便利贴”¶
在马上要开始的 Web 开发实战中,你会经常看到类似 @WebServlet、@Data 这样的东西挂在代码头上。它们到底是什么?
1. 什么是注解?¶
注解 (Annotation) 就是贴在代码(类、方法、变量)上的一张“便利贴”或“配置标签”。
注意一个极其核心的概念: 注解本身是不干活的!它只负责携带信息。 真正干活的是读取这些标签的“幕后黑手”(比如 Java 编译器,或者 Tomcat 服务器运行时用到的一种叫做“反射”的技术)。
💡 生活比喻:
你在超市买水果,苹果上贴了一个标签@打折。
这个标签自己能让价格变低吗?不能。
但是,当收银员(Tomcat 服务器)看到这个@打折标签时,他就会在系统里给你按 8 折结账。
2. 括号里的参数:给便利贴加点“详细备注”¶
有时候,光贴一个 @打折 标签还不够,收银员会问:“到底打几折?” 这时候,我们就需要在括号里加上具体的参数(属性值)。
注解括号里的内容,本质上就是传递给“幕后黑手”的具体指令参数。
- 带参数的便利贴:
@打折(discount = 0.8)告诉系统,具体按 8 折计算。 - 带多个参数的便利贴:在 Servlet 开发中,你可能会看到:
@WebServlet(name = "LoginServlet", urlPatterns = "/login", loadOnStartup = 1)这就像贴了一张信息量满满的标签,告诉 Tomcat:“这个类的代号叫 LoginServlet,它负责处理/login的网址请求,并且在服务器一启动时就把这个类加载进内存。”
😎 一个常见的“偷懒”语法(单值省略):
如果在定义注解时,里面有一个属性的名字刚好叫 value,并且你只打算给这一个属性赋值,那么 Java 允许你把 value = 这几个字母省略掉!
所以,你在代码里最常看到的:
@WebServlet("/login")
其实就是 @WebServlet(value = "/login") 的简写!这种设计纯粹是为了让程序员少敲几下键盘,让代码看起来更清爽。
3. 常见的三大类注解¶
① 编译器的检查贴纸 (JDK 自带)¶
最典型的就是我们在前面见过的 @Override。
注意,这个注解后面没有括号,因为它不需要额外的参数。你把它贴在方法上,仅仅是给 Java 编译器发个信号:“嘿!老哥,我这个方法是重写父类的,你帮我检查一下有没有拼错。”
② 简化代码的魔法贴纸 (比如 Lombok 插件)¶
在后续操作数据库时,我们需要写大量的实体类(比如 User、Order)。只要贴上一个 @Data,Lombok 插件看到这个便利贴,就会默默地在底层帮你生成所有的 get/set、无参构造等方法。
③ Web 服务器的“指路牌” (Servlet 核心注解)¶
这是我们在课程中打交道最多的注解!
🕰️ 时代的眼泪:在以前的旧项目中,为了告诉 Tomcat 服务器“哪个网址对应哪段代码”,程序员需要在一个叫
web.xml的文件里写上七八行臃肿的 XML 配置。每次加个网页都要去改,极度痛苦。
现在,我们只需要贴便利贴:
- 贴了
@WebServlet("/login"),Tomcat 启动时一扫描,就会明白:“哦!当用户在浏览器访问/login路径时,就把请求交给这个类处理。” - 贴了
@WebFilter("/*"),Tomcat 就知道这是一个全局过滤器,所有请求(/*代表所有路径)进来之前都要先经过它这道关卡检查。
4. 如何看待满屏的注解?¶
初学者看到框架里密密麻麻的注解和括号里的各种参数,容易感到心虚,其实大可不必。每次看到一个新注解,你只需要在心里问自己三个问题:
- 这个标签是贴给谁看的?(给编译器?给 Tomcat?还是给未来的 Spring 框架?)
- 那个“幕后黑手”看到它之后,会帮我自动做一件什么事情?
- 括号里的参数,是为了给它提供什么补充信息?
理清了这个逻辑,你就能从繁琐的配置中解脱出来,真正体会到框架带来的开发效率飞跃!🚀