拆解Java中——“ 注解 ”和“ 注释 ” 的一切区别Ⅱ

前言:

上一篇,我们讲到了:

注解的引入(简单概述):在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.
     */
    @FunctionalInterface
    interface ItemProcessor<T> {
        void process(T item);
    }

    /**
     * A safe varargs method for adding elements to a collection.
     */
    @SafeVarargs
    public 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 {
    // 父类中的方法 makeSound
    public void makeSound() {
        System.out.println("Some generic animal sound");
    }
}

// 定义一个子类 Dog,继承自 Animal
class Dog extends Animal {
    // 使用 @Override 注解,表明我们正在重写父类的方法
    @Override
    public void makeSound() {
        System.out.println("Bark bark!");
    }
}

// 测试代码
public class Test {
    public static void main(String[] args) {
        Animal myDog = new Dog(); // 创建一个 Dog 对象,但引用类型是 Animal
        myDog.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 注解表明我们正在重写父类的方法
    @Override
    public void makeSound() {
        // 子类中定义了更具体的行为
        System.out.println("Dog barks: Woof woof!");
    }

    // 使用 @Deprecated 注解来标记一个不再推荐使用的方法
    @Deprecated
    public 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依赖

html 复制代码
<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请求时调用此方法
    @Override
    protected 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:允许子类继承父类中的注解

四,自定义注解的使用

声明自定义注解

使用自定义注解

读取和处理自定义注解

我们先把框架列好,下一篇再完结吧,有点多东西。

我们下次见!!

相关推荐
yuanbenshidiaos3 分钟前
QT-------绘图
开发语言·数据库·qt
wangqiaowq3 分钟前
正则表达式中,`$1` 是一个反向引用(backreference),它代表了匹配过程中捕获的第一个子表达式(即第一个括号内的内容)
java·数据库·mysql
dundunmm9 分钟前
【论文阅读】SCGC : Self-supervised contrastive graph clustering
论文阅读·人工智能·算法·数据挖掘·聚类·深度聚类·图聚类
码农老起14 分钟前
深入解析希尔排序:原理、实现与优化
数据结构·算法·排序算法
tazj16 分钟前
IDEA中Lombok不能使用,找不到get方法
java·ide·intellij-idea
斗-匕17 分钟前
Java IO 基础知识总结
java·ubuntu·php
庞传奇1 小时前
【LC】191. 位1的个数
java·数据结构·算法·leetcode
胜天半月子1 小时前
Python | 学习type()方法动态创建类
开发语言·python·学习
Zer0_on2 小时前
C++string类
开发语言·c++
Tomorrow'sThinker2 小时前
25年1月更新。Windows 上搭建 Python 开发环境:Python + PyCharm 安装全攻略(文中有安装包不用官网下载)
开发语言·python·pycharm