Annotation
注解的使用
1 | @TestAnnotation |
元注解
可以注解到其他注解上的注解,也就是基本注解,可以用来规范注解的一些行为
- @Retention –> 注解的存活周期
- RetentionPolicy.SOURCE 注解将被编译器丢弃
- RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃
- RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。
- @Documented –> 能将注解保存到Javadoc中
- @Target –> 注解应用的地方
- ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
- ElementType.CONSTRUCTOR 可以给构造方法进行注解
- ElementType.FIELD 可以给属性进行注解
- ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
- ElementType.METHOD 可以给方法进行注解
- ElementType.PACKAGE 可以给一个包进行注解
- ElementType.PARAMETER 可以给一个方法内的参数进行注解
- ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
@inherited –> 如果父类使用了此注解,那么子类可以继承此注解
1
2
3
4
5
6
7
8@Inherited
@Retention(RetentionPolicy.RUNTIME)
@interface Test {}
@Test
public class A {}
public class B extends A {}@Repeatable –> Java8新注解,多次应用的注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14@interface Persons {
Person[] value();
}
@Repeatable(Persons.class)
@interface Person{
String role default "";
}
@Person(role="artist")
@Person(role="coder")
@Person(role="PM")
public class SuperMan{
}
容器注解
存放注解的容器,本身也是注解。
注解的属性
注解的属性也叫做成员变量。
- 注解只有成员变量,没有方法
- 以无参的方法来声名
- 方法名为成员名
- 返回值为成员类型
- 类型必须是 8 种基本数据类型
- 类
- 接口
- 注解
- 以上各类型的数组
1
2
3
4
5
6
7
8
9@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
int id();
String msg();
}
在使用注解的时候,应该为该注解的属性赋值:1
2
3@TestAnnotation(id=3,msg="hello annotation")
public class Test {
}
注解中属性可以有默认值,默认值需要用 default 关键值指定:1
2
3
4
5
6
7
8
9@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
public int id() default -1;
public String msg() default "Hi";
}
因此在使用的时候无需再赋初值:1
2@TestAnnotation()
public class Test {}
如果注解中属性名为value,那么可以省略属性名直接赋值使用1
2
3
4
5
6public @interface Check {
String value();
}
@Check("hi")
int a;
内置注解
- @Deprecated
- @Override
- @SuppressWarnings
- @FunctionalInterface Java8新特性,函数式接口可以很容易转化为Lamda表达式。
注解与反射
首先可以通过 Class 对象的 isAnnotationPresent() 方法判断它是否应用了某个注解:
1
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {}
然后通过 getAnnotation() 方法来获取 Annotation 对象:
1
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}
或者是 getAnnotations() 方法:
1
public Annotation[] getAnnotations() {}
如果获取到的Annotation不为null,则可以调用它的属性方法了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15@TestAnnotation()
public class Test {
public static void main(String[] args) {
boolean hasAnnotation = Test.class.isAnnotationPresent(TestAnnotation.class);
if ( hasAnnotation ) {
TestAnnotation testAnnotation = Test.class.getAnnotation(TestAnnotation.class);
System.out.println("id:"+testAnnotation.id());
System.out.println("msg:"+testAnnotation.msg());
}
}
}
程序运行结果:1
2id:-1
msg:
注解的作用
- 注解本身对程序运行没有直接关系
- 注解的存在主要是为编译器或APT(Annotation Processing Tool)使用,而要使用的话需要开发者手动调用方法来提取并处理Annotation的信息
总结
- 注解的作用是取决于你想要它做什么