Luckylau's Blog

Java基础之注解

java的注解(Annotation)机制

什么是注解?

​ 在JDK中我们经常看到@Override @SuppressWarnings(“unchecked”),@Deprecated这三种注解。我们好奇的点开其中的一个实现,代码非常简单。其实在我们使用各种开发框架时候,注解也是经常用到的相关的代码,比如SpringBoot里的@RestController,@Autowired等。下面我们就详细介绍一下注解。

1
2
3
4
5
//@Override
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

如何自定义注解?

Java5.0定义了4个标准的meta-annotation类型:@Target,@Retention,@Documented,@Inherited。

@Target

​ 说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。

1
2
3
4
5
6
7
ElementType.CONSTRUCTOR:用于描述构造器
ElementType.FIELD:用于描述域
ElementType.LOCAL_VARIABLE:用于描述局部变量
ElementType.METHOD:用于描述方法
ElementType.PACKAGE:用于描述包
ElementType.PARAMETER:用于描述参数
ElementType.TYPE:用于描述类、接口(包括注解类型) 或enum声明
1
2
3
4
5
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}

@Retention

定义该注解的生命周期。

1
2
3
RetentionPolicy.SOURCE //在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override,
RetentionPolicy.CLASS //在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。
RetentionPolicy.RUNTIME //始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。

@Documented

是否将注解信息添加在java文档中。

@Inherited

定义该注释和子类的关系,是否允许子类继承该注解。

自定义注解的格式:

1
public @interface 注解名 {定义体}

注意事项:

1.可支持基本数据类型,String类型,Class类型,enum类型,Annotation类型,以上所有类型的数组。

2.只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为default默认类型。

3.如果只有一个参数成员,最好把参数名称设为”value”。

示例说明?

当RetentionPolicy.RUNTIME为RetentionPolicy.SOURCE或者RetentionPolicy.CLASS是无打印输出的。

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Contacts {
String name() default "luckylau";
String email() default "laujunbupt0913@163.com";
}
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class Maindemo {
@Contacts
public void output(){
System.out.println("output is running");
}
@Contacts(name="bilibili",email="bili@bili.com")
public void output2(){
System.out.println("output2 is running");
}
public static void main(String[] args) {
Class<Maindemo> myTestClass = Maindemo.class;
try {
Method method = myTestClass.getMethod("output", new Class[]{});
if (method.isAnnotationPresent(Contacts.class))
{
// 获得注解
Contacts annotation = method.getAnnotation(Contacts.class);
// 调用注解的内容
System.out.println(annotation.name());
System.out.println(annotation.email());
}
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
Method method = myTestClass.getMethod("output2", new Class[]{});
if (method.isAnnotationPresent(Contacts.class))
{
// 获得注解
Contacts annotation = method.getAnnotation(Contacts.class);
// 调用注解的内容
System.out.println(annotation.name());
System.out.println(annotation.email());
}
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Luckylau wechat
如果对您有价值,看官可以打赏的!