Java注解

1. 注解概述

注解就是 Java 代码里的特殊标记,是给当前程序的开发者提供必要的信息和标记,是给 Java 编译或者 JVM 提供的必要的数据支持和标记。比如 @Override、@Test 等,作用是让其他程序根据注解信息来决定怎么执行该程序。注解可以用在类、构造方法、成员变量、参数等位置处。注解本质是一个接口,java 中所有注解都是继承了 Annotation 接口。

2. 注解的基本格式

自定义注解格式

public @interface 注解名 {
    public 属性类型 属性名() default 默认值;
}

例如

public @interface MyAnnotation {
    String test1();
    boolean test2() default true;
    String[] test3();
}

Java中的注解是在 JDK5 的时候引入的一种新特性。注解以@符号开头,紧接着是注解名称。注解名称后面的括号中可以包含一些参数或值。

@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(value = {TYPE}) 
@Inherited
public @interface MyAnnotation {
}
3. 元注解
3.1 元注解概念

元注解指的是修饰注解的注解,注解的对象是注解

3.2 三种常用元注解
3.2.1 @Documented

@Documented

标记当前注解参与 Javadoc 操作,可以生成 JavaDoc 文档

3.2.2 @Retention

@Retention:指注解的作用范围,有三种 SOURCE,CLASS,RUNTIME 分别对应代码的编译阶段、生成 .class 字节码文件、运行阶段。

RetentionPolicy.SOURCE

​ 只参与编译阶段,如@Override .注解可以参与代码的编译过程,提供相对应的标记,提示 Java 编译器在编程过程中,检查相对应的代码格式是否满足当前注解的需求。即 SOURCE 只作用在源码阶段,字节码文件中不存在

RetentionPolicy.CLASS

​ 对应注解可以在 Class 文件中存在,但是不会参与程序运行

RetentionPolicy.RUNTIME

​ 对应注解参与编译过程,生成的 .class 字节码文件,并且在程序运行过程中存在,可以利用反射操作获取对应的注解信息,从注解中得到相应的数据内容。

3.2.3 @Target

用于修饰 Annotation 定义,指定被修饰的 Annotation 能用于哪些程序元素,即决定当前注解可以作用于 Java 代码中的哪一部分。@Target 包含一个名为 value 的成员变量,通过枚举来决定当前注解可以使用范围。

枚举类型如下:

ElementType功能概述
ElementType.TYPE表示当前注解可以用于类和接口,以及枚举
ElementType.FIELD表示当前注解可以用于成员变量
ElementType.METHOD表示当前注解可以用于成员方法
ElementType.PARAMETER表示当前注解可以用于成员方法参数 @NotNull
ElementType.CONSTRUCTOR表示当前注解可以用于构造方法
ElementType.ANNOTATION_TYPE表示当前注解可以用于注解
ElementType.LOCAL_VARIABLE表示当前注解可以用于局部变量
ElementType.PACKAGE表示当前注解可以用于包

一个注解可以用于多种类型

public @interface Target {
	ElementType[] value();
}
import static java.lang.annotation.ElementType.*;
// 表示当前注解可以用于方法
@Target({METHOD})

// 表示当前注解可以用于枚举,成员变量,成员方法,构造方法
@Target({TYPE, FIELD, METHOD, CONSTRUCTOR})
4. 注解属性

注解属性支持的数据类型:基本数据类型,String,Enum ,注解,数组

注解属性就是注解中的成员变量,注解中只有成员变量,没有方法。

  1. 注解中如果需要使用属性,属性列表中必须有一个 value 反馈类型任意
  2. 注解属性可以给予默认数据,如果在用户使用当前注解时,没有对指定属性
    进行数据提供,当前注解属性反馈数据为默认数据

MyAnnotation 注解中有 value 和 msg 两个属性,使用时候应该进行赋值

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
    int value;
    String msg;
}
@MyAnnotation(value=1,msg="MyAnnotation")
public class Test{
}

如果注解中只有一个 value 属性,使用注解时,value 名称可以不写,

其他属性都有 default 默认值时,value 名称也可以不写

对没有 default 默认值的属性,在使用注解时,没有提供对应数据,会直接报错

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
    int value;
}

@MyAnnotation("Java")
public class Test{
}
5. 模拟 Junit 框架

自定义注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyTest1 {

}

在 Annotation1 类中定义若干方法,部分方法加上 @MyTest1 注解修饰,部分注解不添加。模拟 Junit,执行添加 @MyTest1 的方法

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Annotation1 {
    @MyTest1
    public void test1() {
        System.out.println("test1 running");
    }
    public void test2() {
        System.out.println("test2 running");
    }
    public void test3() {
        System.out.println("test3 running");
    }
    @MyTest1
    public void test4() {
        System.out.println("test4 running");
    }

    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        Annotation1 a = new Annotation1();
        Class cls = Annotation1.class;

        Method[] declaredMethods = cls.getDeclaredMethods();

        for (Method declaredMethod : declaredMethods) {
            if (declaredMethod.isAnnotationPresent(MyTest1.class)) {
                declaredMethod.invoke(a);
            }
        }
    }
}

执行结果如下:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值