Java中的注解Annotation

目录

一、介绍:

二、 元注解

三、定义注解

四、使用注解

五、处理器


一、介绍:

注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方式,使我们可以在稍后的某个时刻更容易的使用这些数据。
注解是 Java 5 所引入的众多语言变化之一。它们提供了 Java 无法表达的但是你需要完整表述程序所需的信息。因此,注解使得我们可以以编译器验证的格式存储程序的额外信息。注解可以生成描述符文件,甚至是新的类定义,并且有助于减轻编写“样板”代码的负担。通过使用注解,你可以将元数据保存在 Java 源代码中。并拥有如下优势:简单易读的代码,编译器类型检查,使用 annotation API 为自己的注解构造处理工具。即使 Java 定义了一些类型的元数据,但是一般来说注解类型的添加和如何使用完全取决于

二、 元注解

Java 语言中目前有 5 种标准注解(前面介绍过),以及 5 种元注解。元注解用于注解其他的注解

/**
 * 表示注解可以用于哪些地方。可能的 ElementType 参数包括:
 * CONSTRUCTOR:构造器的声明;
 * FIELD:字段声明(包括 enum 实例);
 * LOCAL_VARIABLE:局部变量声明;
 * METHOD:方法声明;
 * PACKAGE:包声明;
 * PARAMETER:参数声明;
 * TYPE:类、接口(包括注解类型)或者 enum 声明。
 */
@Target(ElementType.CONSTRUCTOR)
@Target(ElementType.FIELD)
@Target(ElementType.LOCAL_VARIABLE)
@Target(ElementType.METHOD)
@Target(ElementType.PACKAGE)
@Target(ElementType.PARAMETER)
@Target(ElementType.TYPE)
/**
 * 表示注解信息保存的时长。可选的 RetentionPolicy 参数包括:
 * SOURCE:注解将被编译器丢弃;
 * CLASS:注解在 class 文件中可用,但是会被 VM 丢弃;
 * RUNTIME:VM 将在运行期也保留注解,因此可以通过反射机制读取注解的信息。
 */
@Retention(RetentionPolicy.SOURCE)
@Retention(RetentionPolicy.CLASS)
@Retention(RetentionPolicy.RUNTIME)
/**
 *将此注解保存在 Javadoc 中
 */
@Documented
/**
 * 允许子类继承父类的注解
 */
@Inherited
/**
 * 允许一个注解可以被使用一次或者多次(Java 8)。
 */
@Repeatable

三、定义注解

/**
 * @author 500007
 * @ClassName:
 * @Description:
 * @date 2022年05月13日 09:09:51
 */
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {

    String value() default "";  //因为默认值不能用null,所以可以选用一些特殊符号作为判断标识

    int id() default -1;

    String hairColor() default "";

}

除了 @ 符号之外, @TestAnnotation的定义看起来更像一个空接口。注解的定义也需要一些元注解(meta-annotation),比如 @Target 和 @Retention@Target 定义你的注解可以应用在哪里(例如是方法还是字段)。@Retention 定义了注解在哪里可用,在源代码中(SOURCE),class文件(CLASS)中或者是在运行时(RUNTIME)。

注解通常会包含一些表示特定值的元素。当分析处理注解的时候,程序或工具可以利用这些值。注解的元素看起来就像接口的方法,但是可以为其指定默认值。

不包含任何元素的注解称为标记注解(marker annotation),例如上例中的 @TestAnnotation 就是标记注解。

四、使用注解

package com.example.dzx.annotation;

import lombok.Data;

/**
 * @author 500007
 * @ClassName:
 * @Description:
 * @date 2022年05月13日 09:13:49
 */
@Data
public class Cat {
    /**
     * 姓名
     */
    @TestAnnotation("黄色")  如果不加注解属性 则默认是value
    private String name;
    /**
     * 颜色
     */
    @TestAnnotation(hairColor = "黄色")
    private String color;

    /**
     * 猫吃鱼
     */
    @TestAnnotation(id = 9)
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

 五、处理器

如果没有用于读取注解的工具,那么注解不会比注释更有用。使用注解中一个很重要的部分就是,创建与使用注解处理器。Java 拓展了反射机制的 API 用于帮助你创造这类工具。同时他还提供了 javac 编译器钩子在编译时使用注解。

下面是一个非常简单的注解处理器,我们用它来读取被注解的 Dog 类,并且使用反射机制来寻找 @AnimalAnnotation标记。

package com.example.dzx.annotation;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @author 500007
 * @ClassName:
 * @Description:
 * @date 2022年05月13日 09:19:02
 */
public class AnnotationProcessor {

    public static void operationAnnotation(Class<?> cl) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        //获取类上私有字段;
        Field[] fields = cl.getDeclaredFields();
        StringBuffer stringBuffer = new StringBuffer();
        Arrays.stream(fields).forEach(p->{
            TestAnnotation annotation = p.getAnnotation(TestAnnotation.class);
            if(annotation.value().length()>0){
                stringBuffer.append("我家小猫叫:"+annotation.value());
            }
            if(annotation.hairColor().length()>0){
                stringBuffer.append("\t它的毛发是:"+annotation.hairColor());
            }
        });
        //获取方法
        Method method = cl.getDeclaredMethod("getCat", String.class);
        //获取方法上的注解
        TestAnnotation annotation = method.getAnnotation(TestAnnotation.class);
        if(annotation.id() != -1){
            stringBuffer.append("\t编号为:"+annotation.id());
        }
        //执行getCat方法
        method.invoke(cl.newInstance(),stringBuffer.toString());
    }

    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        operationAnnotation(Cat.class);
    }
}

运行代码,输出如下:

 

 

处理器肯定能做很多事情、你可以对加了注解的方法加一个监听器,然后获取其参数去执行你想执行的方法,这个蛮有用的,其实注解本身并没有什么作用,它只是一个标识或描述,具体行为由你写的处理器去进行执行,这个处理器是运行期间进行的,有的还可以在编译期间进行操作,然后对外进行输出文件,比如说mybatis-plus的生成工具或者类似的框架,还有通常在spring项目中的aop切面,这种算是复杂的处理器了。

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小米吃辣椒2022

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

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

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

打赏作者

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

抵扣说明:

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

余额充值