Java -- 注解的定义和使用

Java – 注解的定义和使用

Java的注解(Annotation)是Java提供的一种对代码进行标记和说明的机制,它不会直接影响程序的执行,但可以被编译器或运行时环境读取,并据此进行特定的处理。注解是Java 5(JDK 1.5)引入的一种特性,它们以@符号开头,后跟注解的名称。

注解的作用

  1. 提供信息给编译器:编译器可以利用注解来检测错误或警告信息。
  2. 编译时和部署时的处理:软件工具可以利用注解信息来生成代码、XML文件等。
  3. 运行时处理:一些注解可以在运行时被读取,并根据注解信息来改变程序的行为。

注解的类型

Java中的注解可以根据其保留策略(Retention Policy)分为三类:

  1. SOURCE:注解只在源码中保留,编译时会被丢弃,不会包含在.class文件中。
  2. CLASS:注解在编译时会被记录在.class文件中,但在运行时无法被JVM保留,因此不能通过反射机制读取。
  3. RUNTIME:注解在运行时可以被JVM保留,因此可以通过反射机制读取注解信息。

内置注解

Java提供了几个内置注解,用于修饰其他注解或类、方法等:

  • @Override:表示一个方法声明打算重写超类中的另一个方法声明。
  • @Deprecated:用@Deprecated注解的程序元素,不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。
  • @SuppressWarnings:指示编译器去忽略注解中声明的警告。

通过@Deprecated使得该方法过时

public class Person {
    @Deprecated
    public void eat(){
        System.out.println("@Deprecated方法");
    }
}

通过@SuppressWarnings(“all”)消除所有警告

@SuppressWarnings("all")
public class Test01 {
    public static void main(String[] args) {
        Person person = new Person();
        person.eat();

        System.out.println("================");

        ArrayList list = new ArrayList();
        list.add(1);
    }
}

定义注解

定义注解使用@interface关键字,后跟注解的名称。注解内部可以定义元素(类似于类的成员变量),元素在使用时可以指定默认值

1.定义:
public @interface 注解名{

}

2.定义属性:增强注解的作用
数据类型 属性名() -> 此属性没有默认值,需要在使用注解的时候为其赋值
数据类型 属性名() default 值 -> 此属性有默认值,如果有需要,还可以二次赋值

3.注解中能定义什么类型的属性呢?
a.8种基本类型
b.String类型,class类型,枚举类型,注解类型
c.以及以上类型的一维数组

public @interface Book {
    //书名
    String bookName();
    //作者
    String[] author();
    //价格
    int price();
    //数量
    int count() default 10;
    
}

使用注解

  1. 注解的使用:
    说白了就是为注解中的属性赋值

  2. 使用位置上:
    在类上使用,方法上使用,成员变量上使用,局部变量上使用,参数位置使用等

  3. 使用格式:
    a.@注解名(属性名 = 值,属性名 = 值…)
    b.如果属性中有数组:
    @注解名(属性名 = {元素1,元素2…})

@Book(bookName = "红楼梦",author = {"高鹗","曹雪芹"},price = 10,count = 20)
public class BookShelf {
}

解析注解 ->AnnotatedElement接口

注解的解析:说白了就是将注解中的属性值获取出来

1.注解解析涉及到的接口 : AnnotatedElement接口
实现类: AccessibleObject, Class, Constructor, Executable, Field, Method, Package, Parameter

2.解析思路:先判断指定位置上有没有使用指定的注解,如果有,获取指定的注解,获取注解中的属性值

a. boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) -> 判断指定位置上有没有指定的注解

比如:判断BookShelf上有没有Book注解

Class bookShelf = BookShelf.class
bookShelf.isAnnotationPresent(Book.class) 

b.getAnnotation(Class annotationClass) ->获取指定的注解,返回值类型为获取的注解类型
比如:获取BookShelf上的Book注解

Class bookShelf = BookShelf.class
boolean result = bookShelf.isAnnotationPresent(Book.class) 
// 如果result为true,证明BookShelf上有Book注解,那就获取
Book book = bookShelf.getAnnotation(Book.class)   

在这里我们会发现通过isAnnotationPresent方法得到的结果却是false , 但是我们明明引用了该注解

那么发生该问题的原因是注解未在内存中成功加载 , 如何解决呢?

这里又要用到另一个概念 --> 元注解

元注解

1.概述:元注解就是管理注解的注解
2.从哪些方面管理呢?
a.控制注解的使用位置
控制注解是否能在类上使用
控制注解是否能在方法上使用
控制注解是否能在构造上使用等

b.控制注解的生命周期(加载位置)
控制注解是否能在源码中出现
控制注解是否能在class文件中出现
控制注解是否能在内存中出现

3.怎么使用:
a.@Target:控制注解的使用位置
属性:ElementType[] value();
ElementType是一个枚举,里面的成员可以类名直接调用
ElementType中的成员:
TYPE:控制注解能使用在类上
FIELD:控制注解能使用在属性上
METHOD:控制注解能使用在方法上
PARAMETER:控制注解能使用在参数上
CONSTRUCTOR:控制注解能使用在构造上
LOCAL_VARIABLE:控制注解能使用在局部变量上

b.@Retention:控制注解的生命周期(加载位置)
属性:RetentionPolicy value();
RetentionPolicy是一个枚举,里面的成员可以类名直接调用
RetentionPolicy中的成员:
SOURCE:控制注解能在源码中出现 -> 默认
CLASS:控制注解能在class文件中出现
RUNTIME:控制注解能在内存中出现

介绍完相关概念后我们对类进行修改 , 调整加载位置 , 这样就可以成功运行了

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Book {
    //书名
    String bookName();
    //作者
    String[] author();
    //价格
    int price();
    //数量
    int count() default 10;
}

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

攒了一袋星辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值