> For the complete documentation index, see [llms.txt](https://xiaoxiami.gitbook.io/java/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://xiaoxiami.gitbook.io/java/javaji-chu/mian-xiang-dui-xiang/gao-ji-te-xing/zhu-jie.md).

# 注解

**概念**：和注释一样，都是解释说明程序。但注解是给计算机看的。不改变原有的逻辑，JVM在编译或运行期读取注解，根据不同的注解类型做相应的处理。

**定义**：注解（Annotation）/元数据。一种代码级别的说明。JDK1.5后引入可声明在包、类、字段、方法、局部变量、方法参数等的前面，对元素进行说明，注释。

**本质**：注解本质上就是一个接口，默认继承Annotation接口（lang包下）

**使用注解**：@注解名称

**作用**：

* ①编写文档：生成文档doc文档
* ②代码分析：对代码进行分析【使用反射】
* ③编译检查：编译器能实现基本的编译检查【Override】

**常用注解**：@Override ：重写；@Deprecated：表示已过时；@SuppressWarnings：压制警告。一般传递参数all【@SuppressWarnings("all")】

## 自定义注解

格式：

```
元注解
public @interface 注解名称{
    属性列表;
}
```

属性：接口中的抽象方法。返回值类型【基本数据类型、String、枚举、 注解以及它们的数组】

要求：

* 1.定义属性，使用时需给属性赋值。
* 2.如用default关键字给属性默认初始化值，使用注解时可以不进行属性的赋值。
* 3.如只有一个属性需要赋值且属性名称是value，则value可以省略。
* 4.数组赋值时用{}包裹。数组只有一个值可省略{}。

示例

```
package com.sire.source.jdknew.annotation;
/*注解演示*/
// 定义注解
@interface MyAnno1 {
    /*属性：基本数据 字符串 注解 枚举以及它们的数组*/
    int intVal();
    String strVal() default "sire";// 加上默认值在使用注解的时候可以不用复制
   /* MyAnn anVal();
    Sire enuVal();*/
    int[] arrVal();
    int value();
}
@interface MyAnn {}
enum Sire{
    aa;
}
// 使用注解
/*@MyAnno1(intVal = 23,arrVal = 34)*/
@MyAnno1(intVal = 23,arrVal = {2,6},value= 45)
public class MyAnno {}
```

## 元注解

**概述**：用于描述注解的注解

```
@Target：注解能够作用的位置。ElementType取值：TYPE：作用于类；METHOD：作用于方法；FIELD：作用于成员变量
@Retention：注解被保留的阶段。@Retention(RetentionPolicy.RUNTIME)：当前描述的注解，class字节码文件会保留，并被JVM读取。
@Documented：api文档是否会抽取到注解。
@Inherited：描述注解是否被子类继承
```

示例

```java
package com.sire.source.jdknew.annotation;

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

/*演示元注解*/
@Target(ElementType.METHOD)
@interface Anno2{
    int value();
}
/*@Anno2(23) 报错，只能允许在方法上*/
public class TestAnno2 {
    @Anno2(23)
    public void run(){}
}
```

## 综合案例

概述：在类上加自定义注解并写一个测试类进行测试

### 自定义注解

```java
package com.sire.source.jdknew.annotation;

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 check {
}
```

### 计算器类

```java
package com.sire.source.jdknew.annotation;
/*计算器*/
public class Calc {
    @check
    public void add(){
        System.out.println(Integer.parseInt("a"));
        System.out.println("1+0="+(1+0));
    }
    @check
    public void sub(){
        System.out.println("1-0="+(1-0));
    }
    @check
    public void mut(){
        System.out.println("1*0="+(1*0));

    }@check
    public void del(){
        System.out.println("1/0="+(1/0));
    }

}
```

### 测试类

```java
package com.sire.source.jdknew.annotation;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;

/*测试方法*/
public class TestCalc {
    public static void main(String[] args) throws Exception {
        Calc c = new Calc();
        // 1.获取对象
        Class<Calc> clazz = (Class<Calc>) c.getClass();
        // 2.获取所有方法
        Method[] methods = clazz.getMethods();
        int num = 0;// 异常出现次数
        // 异常保存
        BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
        // 3.循环所有方法
        for(Method method:methods){
            if(method.isAnnotationPresent(check.class)){
                try {
                    // 4.唤醒方法
                    method.invoke(c);
                } catch (Exception e) {
                    num++;
                    // 保存异常信息
                    bw.write("第"+num+"次异常");
                    bw.newLine();
                    bw.write("出现异常的方法："+method.getName());
                    bw.newLine();
                    bw.write("异常名称："+e.getCause().getClass().getName());
                    bw.newLine();
                    bw.write("异常信息："+e.getCause().getMessage());
                    bw.newLine();
                }
            }
        }
        bw.write("---------------------------------------\n");
        bw.write("总共发生了"+num+"次异常");
        // 6.刷新关闭
        bw.flush();
        bw.close();
    }
}
```

效果

控制台

![](/files/-LxWYWXIEIM-9bn5U1Qj)

文本文件内容

![](/files/-LxWYZwn7wTgQBpdflwT)
