注解

注解就是带有一定功能的注释。

内置的注解

@Override

该注解我们在前面的学习中也见到过多次了,这个注解是声明下面的方法重写了超类中的方法,如果注解下面的方法没有重写超类中的方法,则编译器报错。

@Deprecated

这个注解表示该程序元素是不鼓励使用的,因为通常的,它是危险的,或者是已经存在更好的替代方法。该注解会使编译器在出现该程序元素的代码处发出警告。

@SuppressWarnings("…")

镇压警告。

它与前面两种注解不太相同,这个注解需要一个参数。

SuppressWarnings常用的参数的表格:

参数 说明
deprecation 使用了不赞成使用的类或方法时的警告
unchecked 执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型。
fallthrough 当 Switch 程序块直接通往下一种情况而没有 Break 时的警告。
path 在类路径、源文件路径等中有不存在的路径时的警告。
serial 当在可序列化的类上缺少 serialVersionUID 定义时的警告。
finally 任何 finally 子句不能正常完成时的警告。
all 关于以上所有情况的警告。

元注解

元注解的作用是负责注解(定义)其他的注解。

@Target(value = …)

描述注解适用的范围(注解可以用在什么地方)。

...处填入java.lang.annotation.ElementType 枚举类型,ElementType 常用的枚举常量在下表:

名称 说明
CONSTRUCTOR 用于构造方法
FIELD 用于成员变量(包括枚举常量)
LOCAL_VARIABLE 用于局部变量
METHOD 用于方法
PACKAGE 用于包
PARAMETER 用于类型参数(JDK 1.8新增)
TYPE 用于类、接口(包括注解类型)或 enum 声明

例:

TestAnnotation:

1
2
3
@Target(value = {ElementType.METHOD, ElementType.TYPE})
public @interface TestAnnotation {
}

Test:

1
2
3
4
5
6
public class Test {
@TestAnnotation
public static void main(String[] args) {
System.out.println("Hello World!");
}
}

@Retention(value = …)

表示需要在什么级别保存该注释信息,用于描述注解的生命周期。

...处填入java.lang.annotation.RetentionPolicy 枚举类型,RetentionPolicy 有 3 个枚举常量,如下所示:

SOURCE:在源代码时,该注解生效;

CLASS:在class文件时,该注解仍然生效;

RUNTIME:在运行的时候,该注解仍然生效;

生命周期:SOURCE < CLASS < RUNTIME(常用)

@Documented

说明该注解将会包含在javadoc中。

@Inherited

说明子类可以继承父类中的该注解。

自定义注解

使用@interface自定义注解时,自动继承了java.lang.annotation接口。

自定义注解一般以public @interface ...的格式,在类里生命一个注解时候,需去除public

一般来说,当注解内参数只有一个值时,值的名字可以命名为vlaue。因为在注解内参数只有一个值且值的名字为value的时候,往往可以将value省略。

如果自定义注解里没有成员,则表明是一个标识作用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.lang.annotation.*;

public class Test {
@MyAnnotation(name = "test")
public void test1() {
}

@MyAnnotation2("test")//只有一个参数可以省略value,而且省略只能省略以value命名的参数
public void test2() {
}
}

@Target(value = {ElementType.TYPE, ElementType.METHOD})//指定注解的作用目标
@Retention(RetentionPolicy.RUNTIME)//指定注解的生命周期
@interface MyAnnotation {
//注解的参数:参数类型+参数名();
String name() default "";//default表示默认值参数
int id() default -1;//如果默认值是-1,则表示不存在
}

@Target(value = {ElementType.TYPE, ElementType.METHOD})//指定注解的作用目标
@Retention(RetentionPolicy.RUNTIME)//指定注解的生命周期
@interface MyAnnotation2 {
String value();
}

可重复注解

jdk8之前,当我们需要写两个相同的注解A但不同值得时,我们需要造多一个注解B,内部值设置为注解A数组,然后使用注解B包含两个注解A完成这个操作:

1
2
3
4
5
6
7
8
9
10
public class Demo {
@BigTest({@Test("1"), @Test("2")})
public static void main(String[] args) {}
}
@interface Test{
String value();
}
@interface BigTest{
Test[] value();
}

在jdk8之后引入了一个新的元注解,使得我们可以重复注解——@Repeatable():

  1. 在注解A中声明@Repeatable(),成员值为注解B
  2. 注解A与注解B的Target、Retention需要相同
1
2
3
4
5
6
7
8
9
10
11
12
public class Demo {
@Test("1")
@Test("2")
public static void main(String[] args) {}
}
@Repeatable(BigTest.class)
@interface Test{
String value();
}
@interface BigTest{
Test[] value();
}