拆解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:允许子类继承父类中的注解

四,自定义注解的使用

声明自定义注解

使用自定义注解

读取和处理自定义注解

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

我们下次见!!

相关推荐
柒七爱吃麻辣烫12 分钟前
在Linux中安装JDK并且搭建Java环境
java·linux·开发语言
极小狐21 分钟前
极狐GitLab 容器镜像仓库功能介绍
java·前端·数据库·npm·gitlab
极小狐23 分钟前
如何构建容器镜像并将其推送到极狐GitLab容器镜像库?
开发语言·数据库·机器学习·gitlab·ruby
MarkHard12325 分钟前
Leetcode (力扣)做题记录 hot100(34,215,912,121)
算法·leetcode·职场和发展
努力的搬砖人.1 小时前
如何让rabbitmq保存服务断开重连?保证高可用?
java·分布式·rabbitmq
_星辰大海乀1 小时前
数据库约束
java·数据结构·数据库·sql·链表
多多*1 小时前
Java反射 八股版
java·开发语言·hive·python·sql·log4j·mybatis
正在走向自律1 小时前
从0到1:Python机器学习实战全攻略(8/10)
开发语言·python·机器学习
爱喝茶的小茶1 小时前
构造+简单树状
数据结构·算法
悦悦子a啊1 小时前
PTA:jmu-ds-最短路径
c++·算法·图论