注解

概念

  • Java 注解是在 JDK5 时引入的新特性,注解(也被称为 元数据
  • 为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便地使用这些数据
  • 注解类型定义指定了一种新的类型,一种特殊的接口类型
  • 在关键词 interface 前加 @ 符号也就是用 @interface 来区分注解的定义和普通的接口声明

作用

提供信息给编译器

  • 编译器可以利用注解来探测错误和警告信息,如 @Override@Deprecated

编译阶段时的处理

  • 软件工具可以用来利用注解信息来生成代码、HTML 文档或者做其它相应处理
  • @Param@Return@See@Author 用于生成 Javadoc 文档

🐤doc 文档生成

/**
 * @author BNTang
 **/
public class Client {
    /**
     * 登录
     *
     * @param userName 用户名
     * @param password 密码
     * @return boolean true(登录成功),否则为登录失败
     */
    public boolean login(String userName, String password) {
        if ("zs".equals(userName) && "1234".equals(password)) {
            return true;
        } else {
            return false;
        }
    }
}
javadoc -encoding utf-8 .\Client.java

运行时的处理

  • 注解可以在程序运行的时候接受代码的提取
  • 通过代码里面标识注解对代码进行分析

JDK 中预定义的一些注解

@Override

  • 检测被该注解标注的方法是否是继承自父类 (接口) 的

@Deprecated

  • 该注解标注的内容,表示已过时

@SuppressWarnings

  • 压制警告
  • 一般传递参数 all,例如:@SuppressWarnings("all")
/**
 * @author BNTang
 */
@SuppressWarnings("all")
public class AnnotationDemo {

    @Override
    public String toString() {
        return super.toString();
    }

    @Deprecated
    public void test1() {
        System.out.println("test1");
    }

    public void test2() {
        // 如果没有SuppressWarnings会提示过期
        test1();
        new Date().toLocaleString();
    }
}

自定义注解

基本格式

元注解
public @interface 注解名称 {
	属性列表;
}
/**
 * @author BNTang
 */
public @interface MyAnnotation {
}

本质

  • 拿到字节码进行反编译
javap .\MyAnnotation.class

public interface top.it6666.MyAnnotation extends java.lang.annotation.Annotation{}
  • 注解本质上就是一个接口,该接口默认继承 Annotation 接口

属性列表

🐤接口中的抽象方法,返回值类型的要求,属性的返回值类型有下列取值

  • 基本数据类型
  • String
  • 枚举
  • 注解
  • 以上类型的数组
/**
 * @author BNTang
 */
public @interface MyAnnotation {

    int testOne();

    String testTwo();

    MyEnum test3();

    MyAnnotationTest test4();

    String[] test5();

    // 报错, 不能是自定义类
    // Login test6();
    
    // 报错, 返回值不能为空
    // void test7();
}

🐤定义了属性,在使用时需要给属性赋值

  • 如果定义属性时,使用 default 关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值

  • 如果只有一个属性需要赋值,并且属性的名称是 value,则 value 可以省略,直接定义值即可

  • 数组赋值时,值使用 {} 包裹。如果数组中只有一个值,则 {} 可以省略

元注解

🐤什么是元注解

  • 用于描述注解的注解
  • JDK 提供的注解,用于描述我们自己定义的注解

@Target

  • 作用:描述注解能够作用的位置

🐤ElementType 取值

  • TYPE:可以作用于类上
  • METHOD:可以作用于方法上
  • FIELD:可以作用于成员变量上

/**
 * @author BNTang
 */
@Target(value = {ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
public @interface MyAnnotation {
    int age();

    String[] name();
}

/**
 * @author BNTang
 **/
@MyAnnotation(age = 10, name = "BNTang")
public class Person {
    @MyAnnotation(age = 33, name = "JonathanLee")
    private String name;

    @MyAnnotation(age = 23, name = "my name is BNTang")
    public void show() {

    }
}

@Retention

  • 描述注解被保留的阶段
  • @Retention(RetentionPolicy.RUNTIME)
  • 当前被描述的注解,会保留到 class 字节码文件中,并被 JVM 读取到

@Documented

  • 描述注解是否被抽取到 api 文档中

@Inherited

  • 描述注解是否被子类继承

解析注解

🐤解析注解也就是使用注解当中传递的内容

使用步骤

  • 获取注解定义的位置的对象
  • 获取指定的注解

获取类上的注解

/**
 * @author BNTang
 **/
public class Client {
    public static void main(String[] args) {
        Class<Person> personClass = Person.class;

        // 获取字节码上面的注解对象
        MyAnnotation myAnnotation = personClass.getAnnotation(MyAnnotation.class);

        String[] name = myAnnotation.name();
        System.out.println(Arrays.toString(name));

        int age = myAnnotation.age();
        System.out.println(age);
    }
}

获取指定方法上的注解

/**
 * @author BNTang
 **/
public class Person {

    private String name;

    @MyAnnotation(age = 23, name = {"BNTang", "JonathanLee"})
    public void show() {

    }

    public static void main(String[] args) throws NoSuchMethodException {
        Class<Person> personClass = Person.class;

        Method show = personClass.getMethod("show");

        // 获取指定方法上面的注解对象
        MyAnnotation myAnnotation = show.getAnnotation(MyAnnotation.class);

        String[] name = myAnnotation.name();
        System.out.println(Arrays.toString(name));

        int age = myAnnotation.age();
        System.out.println(age);
    }
}

获取指定字段上的注解

/**
 * @author BNTang
 **/
public class Person {

    @MyAnnotation(age = 23, name = {"BNTang", "JonathanLee"})
    public String name;

    public static void main(String[] args) throws NoSuchFieldException {
        Class<Person> personClass = Person.class;

        // 这里获取的字段是公共的获取私有的在反射文章当中有讲解不会的自行去参考即可
        Field nameField = personClass.getField("name");

        // 获取指定字段上面的注解对象
        MyAnnotation myAnnotation = nameField.getAnnotation(MyAnnotation.class);

        String[] name = myAnnotation.name();
        System.out.println(Arrays.toString(name));

        int age = myAnnotation.age();
        System.out.println(age);
    }
}
  • 内部动态的创建一个实现类,实现了 MyAnnotation 注解接口
posted @   BNTang  阅读(67)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示