本文涉及以下这些内容,如果不清楚的话,可以看一下,相信会对你有些许帮助。:
1)使用IntelliJ IDEA 2018查看字节码。
2)使用IntelliJ IDEA 2018生成帮助文档
本文主要针对于java8,java8定义了6个标准元注解:@Target,@Retention,@Documented,@Inherited,@Repeatable和@Native。
1.@Target注解。
@Target注解的作用是:描述注解的使用范围(即被修饰的注解可以用在什么地方)。@Target注解用来说明那些被他注解的注解类可修饰的对象范围。
@Target注解源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
@Target注解的枚举参数:
public enum ElementType {
//类,接口,枚举类
TYPE,
//成员变量,枚举常量
FIELD,
//方法
METHOD,
//形式参数
PARAMETER,
//构造方法
CONSTRUCTOR,
//局部变量
LOCAL_VARIABLE,
//注解
ANNOTATION_TYPE,
//包
PACKAGE,
//类型参数
TYPE_PARAMETER,
//类型使用
TYPE_USE
}
2.@Retention注解。
@Retention注解的作用是:描述注解保留的时间范围(即:被描述的注解在它所修饰的类中可以被保留到何时)。@Retention注解用来限定那些被他所注解的注解类在注解到其他类上以后,可被保留到何时。
@Retention注解源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
@Retention注解的枚举参数:
public enum RetentionPolicy {
//源文件保留
SOURCE,
//编译期保留,默认值
CLASS,
//运行期保留,可通过反射去获取注解信息
RUNTIME
}
下面我们举个例子:
注解:
@Retention(RetentionPolicy.SOURCE)
public @interface SourcePolicy {
}
注解:
@Retention(RetentionPolicy.CLASS)
public @interface ClassPolicy {
}
注解:
@Retention(RetentionPolicy.RUNTIME)
public @interface RuntimePolicy {
}
测试类:
public class RetentionTest {
@SourcePolicy
public void sourcePolicy(){
}
@ClassPolicy
public void classPolicy(){
}
@RuntimePolicy
public void runtimePolicy(){
}
}
RetentionPolicy 类的字节码文件中三个方法的部分:
public void sourcePolicy();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=0, locals=1, args_size=1
0: return
LineNumberTable:
line 8: 0
LocalVariableTable:
Start Length Slot Name Signature
0 1 0 this Lannotation/RetentionTest;
public void classPolicy();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=0, locals=1, args_size=1
0: return
LineNumberTable:
line 13: 0
LocalVariableTable:
Start Length Slot Name Signature
0 1 0 this Lannotation/RetentionTest;
RuntimeInvisibleAnnotations:
0: #14()
public void runtimePolicy();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=0, locals=1, args_size=1
0: return
LineNumberTable:
line 18: 0
LocalVariableTable:
Start Length Slot Name Signature
0 1 0 this Lannotation/RetentionTest;
RuntimeVisibleAnnotations:
0: #17()
根据上面方法的字节码我们可以看出:
1)编译器没有记录sourcePolicy方法的注解信息。
2)编译器使用了RuntimeInvisibleAnnotations属性记录classPolicy方法的注解信息,使用RuntimeVisibleAnnotations属性记录runtimePolicy方法的注解信息。
3.Documented注解。
Documented注解的作用是:描述在使用javadoc工具为类生成帮助文档时是否要保留其注解信息。
Documented注解源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
下面我们举个例子:
注解:
@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface MyDocumentedAnnotation {
}
测试类:
@MyDocumentedAnnotation
public class MyDocumentedTest {
@MyDocumentedAnnotation
@Override
public String toString(){
return this.toString();
}
}
查看生成的帮助文档:
由此我们可以看出@Documented注解的作用。
4.Inherited注解。
Inherited注解的作用是:使被他修饰的注解具有继承性(如果某个类使用了被@Inherited修饰的注解,则其子类将自动具有该注解。)
下面我们举个例子:
注解:
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyInheritedAnnotation {
public String name() default "pengjunlee";
}
父类:
@MyInheritedAnnotation(name = "parent")
public class Parent {
}
子类:
public class Child extends Parent {
public static void main(String[] args) {
Class<Child> child = Child.class;
MyInheritedAnnotation annotation = child.getAnnotation(MyInheritedAnnotation.class);
System.out.println(annotation.name());
}
}
输出:
parent
5.@Repeatable注解。
@Repeatable注解的作用是:用于声明标记的注解为可重复类型注解,可以在同一个地方多次使用。
@Repeatable 注解源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable {
Class<? extends Annotation> value();
}
下面我们举个例子:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyRepeatableAnnotation {
RepeatableAnnotationTest[] value();
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(MyRepeatableAnnotation.class)
public @interface RepeatableAnnotationTest {
String key();
String value();
}
@RepeatableAnnotationTest(key = "aa",value = "11")
@RepeatableAnnotationTest(key = "bb",value = "22")
public class RepeatableTest {
public static void main(String[] args) {
RepeatableAnnotationTest[] annotation = RepeatableTest.class.getAnnotation(MyRepeatableAnnotation.class).value();
for (RepeatableAnnotationTest a : annotation) {
System.out.println(a);
}
}
}
输出:
@annotation.RepeatableAnnotationTest(key=aa, value=11)
@annotation.RepeatableAnnotationTest(key=bb, value=22)
6.@Native注解。
@Native注解修饰成员变量,则表示这个变量可以被本地代码引用,常常被代码生成工具使用。对于@Native注解不常使用,了解即可。