前言:
上一篇,我们讲到了:
①注解的引入(简单概述):在jdk5.0的时候
②注解与注释的区别:
- 注释 是为了帮助人类阅读代码,不会对程序的执行产生任何影响。
- 注解 是为了给编译器或运行时环境提供额外的信息,可能会影响程序的编译或运行行为。
并通过 比喻(日记和标签,贴纸)和 举代码例子 的方式帮助大家更直观的了解二者的区别
③注解的重要性:
并通过 传统方式(XML配置)和 现代方式(使用注解)代码比对的方式,带大家更直观的明白注解的好处
- 简化配置
- 提高开发效率
开始之前,大家可不可以给小编一个免费的赞或者关注(我们一起进步啊!!!!)
一,常见的Annotation 作用:
1:生成文档相关的注解
- @author 标明开发该类模块的作者,多个作者之间使用,分割
- @version 标明该类模块的版本
- @see 参考转向,也就是相关主题
- @since 从哪个版本开始增加的
- @param 对方法中某参数的说明,如果没有参数就不能写
- @return 对方法返回值的说明,如果方法的返回值类型是void就不能写
- @exception 对方法可能抛出的异常进行说明 ,如果方法没有用throws显式抛出的 异常就不能写
- @FunctionalInterface:指定一个接口为函数式接口,即仅有一个抽象方法的接口,适用于Lambda表达式的使用。
以上是小编总结的一些常用的注解。
来个简单例子:(其中包含的自定义注解,我们后面会讲到)
java">import java.util.List;// 自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyCustomAnnotation {String value() default "Default Value";
}// 使用自定义注解
@MyCustomAnnotation("This is a custom annotation example")
class Example {// 作者和版本信息@author("John Doe, Jane Smith")@version("1.0")/*** A method that processes a list of items.* @param items The list of items to process.* @return The number of processed items.* @throws IllegalArgumentException if the list is null.*/@Override@Deprecated@SuppressWarnings("unchecked")public int processItems(@SuppressWarnings("rawtypes") List items) throws IllegalArgumentException {if (items == null) {throw new IllegalArgumentException("The items list cannot be null.");}return items.size();}/*** A functional interface for processing an item.*/@FunctionalInterfaceinterface ItemProcessor<T> {void process(T item);}/*** A safe varargs method for adding elements to a collection.*/@SafeVarargspublic final <T> void addElements(Collection<T> collection, T... elements) {for (T element : elements) {collection.add(element);}}
}
咱们注意一下:
在实际的Java代码中,@author 和 @version 等是Javadoc标签,不是正式的Java注解,因此在代码中不会直接作为注解使用。
如果你想要将这些信息作为注解来使用,你需要自己定义这些注解或者使用第三方库提供的注解。
此外,@Override 和 @Deprecated 是标准的Java注解,而 @SuppressWarnings 和 @FunctionalInterface 是为了确保代码的正确性和优化编译器输出。
2:在编译时进行格式检查(JDK内置的三个基本注解)
2.1@Override: 限定重写父类方法,该注解只能用于方法
- 用于检测被标记的方法为有效的重写方法,如果不是,则报编译错误!
- 只能标记在方法上。
- 它会被编译器程序读取。
举个栗子:
java">// 定义一个父类 Animal
class Animal {// 父类中的方法 makeSoundpublic void makeSound() {System.out.println("Some generic animal sound");}
}// 定义一个子类 Dog,继承自 Animal
class Dog extends Animal {// 使用 @Override 注解,表明我们正在重写父类的方法@Overridepublic void makeSound() {System.out.println("Bark bark!");}
}// 测试代码
public class Test {public static void main(String[] args) {Animal myDog = new Dog(); // 创建一个 Dog 对象,但引用类型是 AnimalmyDog.makeSound(); // 调用的是 Dog 类的 makeSound 方法}
}
代码解释和总结:
①限定重写父类方法
Dog 类的 makeSound() 方法前面加上了 @Override 注解。这意味着我们告诉编译器:“嘿,我在这里是要重写从 Animal 类继承下来的那个 makeSound() 方法哦。” 如果 Animal 类中没有 makeSound() 方法,或者 Dog 类中的 makeSound() 方法签名(包括方法名、参数列表等)与 Animal 类中的不同,那么编译器就会报错,因为它无法找到可以被重写的匹配方法。
②只能标记在方法上
@Override 只能放在方法定义的前面。你不能把它放在变量、构造函数或其他地方。例如,在上面的例子中,我们只在 Dog 类的 makeSound() 方法前使用了 @Override,而不会在任何其他地方使用它。
③它会被编译器程序读取
这意味着当你的代码被编译时,编译器会检查所有带有 @Override 注解的方法,以确保它们确实是在重写父类中的某个方法。如果一切正常,代码就能成功编译;如果有问题,比如拼写错误或方法签名不匹配,编译器就会给出错误信息,帮助你及时发现并修正错误。
2.2@Deprecated: 用于表示所修饰的元素(类,方法等)已过时。通常是因为所修饰 的结构危险或存在更好的选择
2.3@SuppressWarnings: 抑制编译器警告
举个栗子:
java">// 假设我们有一个父类叫做 Animal,它有一个叫 makeSound 的方法。
class Animal {// 这个方法用来表示动物发出的声音public void makeSound() {System.out.println("Animal makes a sound");}
}// 现在我们有一个子类 Dog,它继承自 Animal 类。
class Dog extends Animal {// 使用 @Override 注解表明我们正在重写父类的方法@Overridepublic void makeSound() {// 子类中定义了更具体的行为System.out.println("Dog barks: Woof woof!");}// 使用 @Deprecated 注解来标记一个不再推荐使用的方法@Deprecatedpublic void oldMethod() {// 这是一个过时的方法,应该避免使用System.out.println("This is an old method, please use the new one.");}// 使用 @SuppressWarnings 来抑制未使用的变量警告@SuppressWarnings("unused")private void exampleMethod() {// 假设这里有一个我们暂时不需要使用的变量String unusedVariable = "I am not used in this method.";// 方法体中可能有其他有用的逻辑System.out.println("This method has some logic but also an unused variable.");}// 新的推荐使用的方法public void newMethod() {System.out.println("This is the new and improved method.");}
}public class Main {public static void main(String[] args) {// 创建一个 Dog 对象Dog myDog = new Dog();// 调用重写后的方法myDog.makeSound(); // 输出:Dog barks: Woof woof!// 调用过时的方法(不推荐)myDog.oldMethod(); // 输出:This is an old method, please use the new one.// 调用新的方法myDog.newMethod(); // 输出:This is the new and improved method.}
}
代码解释和总结:
@Override 注解:
当我们在子类中定义了一个与父类同名的方法,并且想要明确地告诉编译器“我是在重写父类的方法”,这时我们可以使用 @Override 注解。
这样做有两个好处:
- ①编译器可以帮助我们检查是否正确地重写了父类的方法。如果我们拼错了方法名或者参数列表不一样,编译器会报错,帮助我们及时发现错误。
- ②它使代码更清晰易读,任何看到这个注解的人都知道这里是在重写父类的方法。
@Deprecated 注解:
如果我们认为某个方法不应该再被使用了,可能是因为它存在风险,或者是有了更好的替代方法,那么我们可以使用 @Deprecated 注解来标记这个方法。这就像给方法贴上了一个“不要使用”的标签。当有人尝试使用这个方法时,IDE(集成开发环境)通常会给出警告提示,并建议使用更新的替代方法。
@SuppressWarnings 注解:
有时候我们的代码可能会引发编译器的警告,比如声明了一个但从未使用的变量。虽然这些警告不会阻止代码运行,但它们可能会让代码看起来不整洁。如果我们确定这些警告是可以忽略的,就可以使用 @SuppressWarnings 注解来告诉编译器“我知道这里有警告,但是请不要显示它们”。需要注意的是,我们应该谨慎使用这个注解,只在确实需要的时候才使用,以确保代码的质量。
3:跟踪代码依赖性,实现替代配置文件功能(小白可不看)
Servlet3.0 提供了注解(annotation),使得不再需要在web.xml文件中进行Servlet的部署。
举个栗子:
Maven依赖
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope>
</dependency>
Servlet类
创建一个简单的Servlet类,它将使用注解来配置URL映射和其他属性。
java">import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;// 使用 @WebServlet 注解来配置Servlet的URL模式、名称等
@WebServlet(name = "HelloWorldServlet", urlPatterns = {"/hello"}, // 定义访问该Servlet的URL路径loadOnStartup = 1 // 指定Servlet启动顺序,值越小优先级越高
)
public class HelloWorldServlet extends HttpServlet {private static final long serialVersionUID = 1L;// 当接收到HTTP GET请求时调用此方法@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 设置响应的内容类型response.setContentType("text/html");// 获取输出流以写入响应内容try (var out = response.getWriter()) {// 向客户端发送HTML响应out.println("<html><body>");out.println("<h1>Hello, World!</h1>");out.println("</body></html>");}}// 如果你也想处理POST请求,可以重写 doPost 方法// @Override// protected void doPost(HttpServletRequest request, HttpServletResponse response)// throws ServletException, IOException {// // POST 请求的处理逻辑// }
}
代码解释和总结:
@WebServlet 注解:
- 他用来替代web.xml中的<servlet>和<servlet-mapping>元素。你可以通过它来定义Servlet的名字、它应该监听的URL模式(即哪些URL会触发这个Servlet),以及启动顺序等。
- name 属性是Servlet的名称,虽然不是必须的,但它可以帮助你识别这个Servlet。
- urlPatterns 属性指定了哪个URL模式会触发这个Servlet。在这个例子中,当用户访问/hello路径时,服务器就会调用HelloWorldServlet。
- loadOnStartup 属性告诉服务器在启动时加载这个Servlet。数值越小,优先级越高;如果没有指定,则默认是在第一次请求时加载。
doGet 方法:
- 这是一个标准的Servlet方法,用于处理HTTP GET请求。当我们访问上面定义的/hello URL时,服务器会调用这个方法。
- 在这里,我们设置了响应的内容类型为text/html,然后通过getWriter()获取输出流,并向客户端发送了一个简单的HTML页面作为响应。
doPost 方法(可选):
- 如果你需要处理POST请求,你可以重写doPost方法。不过在这个简单的例子中,我们只处理GET请求,所以没有实现doPost。
二,三分基本注解:
① @Override
② 10.3.2 @Deprecated
③ @SuppressWarnings
三,元注解:
(1)@Target:用于描述注解的使用范围
(2)@Retention:用于描述注解的生命周期
(3)@Documented:表明这个注解应该被 javadoc工具记录。
(4)@Inherited:允许子类继承父类中的注解
四,自定义注解的使用
声明自定义注解
使用自定义注解
读取和处理自定义注解
我们先把框架列好,下一篇再完结吧,有点多东西。
我们下次见!!